home *** CD-ROM | disk | FTP | other *** search
- /* $Id: ckmco2.c,v 1.9 91/12/27 21:28:52 fdc Exp $
- * $Source: /uw/mackermit/RCS/ckmco2.c,v $
- *------------------------------------------------------------------
- * $Log: ckmco2.c,v $
- * Revision 1.9 91/12/27 21:28:52 fdc
- * Change fatal to macfatal, make sure all lines width 80 or less.
- *
- * Revision 1.8 91/12/15 23:16:45 rick
- * ut9
- *
- * Revision 1.7 91/10/13 13:43:05 rick
- * UT(7)
- *
- * Revision 1.6 91/10/01 12:16:12 rick
- * UT(5)
- *
- * Revision 1.5 91/09/25 12:16:26 rick
- * Command window in TE. Multiple vt100 windows for command window.
- *
- * Revision 1.4 91/09/12 21:50:31 rick
- * UT(3). Install on watsun
- *
- * Revision 1.3 1991/09/12 16:42:51 rick
- * Cleanups.
- *
- * Revision 1.2 1991/09/10 22:21:37 rick
- * Update to UTexas(2)
- *
- * Revision 1.1 1991/09/10 19:17:45 rick
- * Initial revision
- *
- *------------------------------------------------------------------
- * $Endlog$
- */
-
- /*
- * FILE ckmco2.c
- *
- * Module of mackermit: contains code for dealing with the Mac side
- * of terminal emulation.
- */
-
- /*
- Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
- York. Permission is granted to any individual or institution to use this
- software as long as it is not sold for profit. This copyright notice must be
- retained. This software may not be included in commercial products without
- written permission of Columbia University.
- */
- #include "ckcdeb.h"
- #include "ckcasc.h"
- #include "ckmdef.h"
- #include "ckmasm.h" /* Assembler code */
- #include "ckmres.h" /* kermit resources */
- #include "ckmcon.h" /* defines, etc. for terminal emulator */
- #include "ckmptp.h" /* ckm* Prototypes */
-
- extern int escape;
-
- #define ABS(a) ((a) < 0 ? -(a) : (a))
-
- char **myclip_h; /* internal clipboard */
- int myclip_size; /* size of above */
- int my_scrapcount; /* the value of PScrapStuff->scrapCount when we cut */
-
- extern Boolean usingRAMdriver,
- have_128roms; /* true if we are a Plus or better */
-
- RgnHandle dummyRgn; /* dummy region for ScrollRect */
- /* Initialized in mac_init */
-
- long MyCaretTime; /* (UoR) ticks between flashes */
-
- extern Cursor *textcurs, *normcurs, *watchcurs; /* mouse cursor shapes */
-
- extern int to_printer; /*JAO*/
- extern int to_screen; /*JAO*/
- extern int printer_is_on_line_num; /*JAO*/
- extern Handle hPrintBuffer; /*JAO*/
- extern long lPrintBufferSize; /*JAO*/
- extern long lPrintBufferChars; /*JAO*/
- extern long lPrintBufferAt; /*JAO*/
-
- extern DialogPtr bufferingDialog; /*JAO*/
- extern DialogPtr overflowingDialog; /*JAO*/
-
- extern MenuHandle menus[]; /* handle on our menus */ /*JAO*/
-
- /* keyboard handling stuff */
-
- extern char keytable[512]; /* the key redefintion flag table */
- extern modrec modtable[NUMOFMODS]; /* modifier records */
-
- #define myKeyCodeMask 0x7F00
- #define keyModifierMask 0x1F00
- #define ctrlCodeMask 0x1F
- #define metaOrBits 0x80
-
- #define UnmodMask 0x80 /* action bits */
- #define CapsMask 0x40
- #define CtrlMask 0x20
- #define MetaMask 0x10
-
-
- Boolean have_scriptmgr = FALSE;
-
- long old_KCHR, old_SICN; /* pointers to current system key script, icon */
- long cur_KCHR;
- Cursor *lastCursor=0L; /* what we set the cursor to last */
-
-
- /****************************************************************************/
- /****************************************************************************/
- /****************************************************************************/
- /* keyboard event handling routines */
- /****************************************************************************/
-
-
- InitKeyStuff()
- {
- have_scriptmgr = NGetTrapAddress(num_UnknownTrap, 1) !=
- NGetTrapAddress(num_ScriptTrap, 1);
-
- if (have_scriptmgr) {
- old_KCHR = GetScript( smRoman, smScriptKeys);
- old_SICN = GetScript( smRoman, smScriptIcon);
- }
- cur_KCHR = old_KCHR;
-
- UpdateOptKey(1); /* get things set right initially */
- }
-
- UpdateOptKey(int enable)
- {
- int i;
- int futzit = 0;
-
- if (enable) {
- for (i = 0; i < NUMOFMODS; i++) {
- /* shift what to look for into high byte */
- if ((modtable[i].modbits) & (optionKey >> 4))
- /* if Option is selected */
- futzit = 1;
- }
- } else { /* allways turn off when disabling window */
- futzit = 0;
- }
-
- (void) FutzOptKey(futzit);
- }
-
- FutzOptKey(int enable)
- {
- int err;
-
- if (have_scriptmgr) { /* if we are system 4.1 or later... */
- if (enable) { /* no deadkeys */
- if (cur_KCHR != old_KCHR)
- return (1); /* we are allready fine */
- if (GetEnvirons(smKeyScript) == smRoman) {
- /* set the key map only if in roman script */
- err = SetScript (smRoman, smScriptKeys, NODEAD_KCHR);
- if (err != noErr) {
- printerr ("Trouble setting custom keymap (KCHR):", err);
- return (0);
- }
- /* set the icon */
- err = SetScript (smRoman, smScriptIcon, NODEAD_SICN);
- if (err != noErr) {
- printerr ("Trouble setting custom keymap icon (SICN):",
- err);
- return (0);
- }
- KeyScript (smRoman);
- cur_KCHR = NODEAD_KCHR;
- return (1); /* success! */
- } else {
- printerr("Can't disable Option key -- you have a non-US keyboard",0);
- return (0);
- }
- } else { /* back to normal */
- if (cur_KCHR == old_KCHR)
- return (1); /* we are allready fine */
- /* set the key map */
- err = SetScript (smRoman, smScriptKeys, old_KCHR);
- if (err != noErr) {
- printerr ("Trouble resetting default keymap (KCHR):", err);
- return (0);
- }
- /* set the icon */
- err = SetScript (smRoman, smScriptIcon, old_SICN);
- if (err != noErr) {
- printerr ("Trouble resetting default keymap icon (SICN):",
- err);
- return (0);
- }
- KeyScript (smRoman);
- cur_KCHR = old_KCHR;
- return (1); /* success! */
- }
- } else {
- /* do something or other to do the old way */
- /* printerr("Kermit can't disable Option on old systems",0); */
- }
- return (0);
- }
-
-
- /****************************************************************************/
- /* return the ASCII character which is generated by the keyCode specified */
- /* with no modifiers pressed */
- /****************************************************************************/
- unsigned char DeModifyChar (long keyCode, long modifiers)
- {
- long c;
- long mystate;
- short s_keycode;
- Handle kchr_h;
- THz curZone;
-
- #ifdef COMMENT
- ProcHandle KeyTrans;
-
- if (keyCode > 64)
- KeyTrans = (ProcHandle) 0x2A2; /* keypad decode */
- else
- KeyTrans = (ProcHandle) 0x29E; /* keyboard decode */
-
- SaveRegs (); /* save all registers */
- AllRegs ();
-
- /* setup regs for procedure call */
- /* loadD1 ((long) modifiers); */ /* no modifiers */
- loadD1 ((long) 0); /* no modifiers */
- loadD2 ((long) keyCode); /* set the keycode */
- loadA0 (*KeyTrans); /* load the content of Key1Trans to A0 */
-
- /* run the translation routine */
- execute (); /* call the Key1Trans procedure */
-
- /* move the result from reg D0 to c */
- loadA0 (&c); /* set destination address */
- pushD0 (); /* move register D0 to stack */
- poptoA0 (); /* load the stacktop to (A0) */
-
- RestoreRegs (); /* restore all registers */
- AllRegs ();
-
- #endif /* COMMENT */
-
- if (have_scriptmgr) { /* if we are system 4.1 or later... */
- mystate = 0;
-
- kchr_h = GetResource('KCHR', cur_KCHR);
- if (kchr_h == NIL) {
- printerr("DeModifyChar: couldn't get KCHR address",0);
- return(0);
- }
- LoadResource(kchr_h);
- HLock(kchr_h);
-
- s_keycode = (modifiers & 0xff00) | (keyCode & 0xff);
-
- c = KeyTrans(*kchr_h, s_keycode, &mystate);
- HUnlock(kchr_h);
- curZone = GetZone(); /* as per John Norstad's (Disinfectant) */
- SetZone(HandleZone(kchr_h)); /* "Toolbox Gotchas" */
- ReleaseResource(kchr_h);
- SetZone(curZone);
- }
- return (c);
- } /* DeModifyChar */
-
-
-
- unsigned char obuf[2] = {1, 0}; /* single char output buffer */
-
- /****************************************************************************/
- /* send a character to the line if it is in ASCII range. Do local echo if */
- /* necessary */
- /****************************************************************************/
- OutputChar (struct termw *termw, unsigned char c)
- {
-
- /*
- * PWP: NO 7 bit masking!!! If we do this, then I can't use Emacs, and
- * the European users will be VERY unhappy, 'cause they won't be able to
- * send all of their characters.
- */
-
- obuf[1] = c; /* store character */
- writeps (obuf); /* and write it out */
-
- if (duplex != 0) {
- cursor_erase (termw); /* remove from screen */
- printem (termw, &obuf[1], 1); /* Echo the char to the screen */
- flushbuf(termw); /* flush the character */
- cursor_draw(termw); /* put it back */
- }
- } /* OutputChar */
-
- #ifdef COMMENT
- /****************************************************************************/
- /* Bittest returns the setting of an element in a Pascal PACKED ARRAY [0..n]
- OF Boolean such as the KeyMap argument returned by GetKey
- /****************************************************************************/
- Boolean
- bittest (bitmap, bitnum)
- char bitmap[];
- int bitnum;
- {
- return (0x01 & (bitmap[bitnum / 8] >> (bitnum % 8)));
- } /* bittest */
-
- /* PWP: or, as a macro, */
- #define bittest(bitmap,bitnum) (0x01 & (bitmap[bitnum / 8] >> (bitnum % 8)))
-
- #endif /* COMMENT */
-
-
- /****************************************************************************/
- /* Process a character received from the keyboard */
- /****************************************************************************/
- handle_char (struct termw *termw, EventRecord *evt)
- {
- short i;
- short len;
- short theCode;
- short modCode;
- short theModBits;
- char flags;
- char tmpstr[256];
- unsigned char c;
-
- /* (UoR) check for auto repeated keys */
- if ((termw->autorepeat == FALSE) && (evt->what == autoKey))
- return;
-
- ObscureCursor (); /* PWP: hide the cursor until next move */
-
- modCode = evt->modifiers & keyModifierMask;
- theCode = ((evt->message & myKeyCodeMask) >> 8) + (modCode >> 1);
-
- /* check for a special code for this key */
- if (BitTst (keytable, theCode)) {
- GetMacro (theCode, &flags, tmpstr); /* get the macrostring */
-
- if (flags) { /* check special flags */
- switch (flags) {
- case shortBreak:
- sendbreak (5);
- return;
-
- case longBreak:
- sendbreak (70);
- return;
-
- case leftArrowKey:
- do_arrow (termw, leftARROW);
- return;
-
- case rightArrowKey:
- do_arrow (termw, rightARROW);
- return;
-
- case upArrowKey:
- do_arrow (termw, UPARROW);
- return;
-
- case downArrowKey:
- do_arrow (termw, DOWNARROW);
- return;
-
- case keycomma:
- case keyminus:
- case keyperiod:
- /* there is no keyslash */
- case key0:
- case key1:
- case key2:
- case key3:
- case key4:
- case key5:
- case key6:
- case key7:
- case key8:
- case key9:
- do_keypad(termw, flags - keycomma);
- return;
-
- case keypf1:
- case keypf2:
- case keypf3:
- case keypf4:
- do_pfkey(termw, flags - keypf1);
- return;
-
- case keyenter:
- do_keyenter(termw);
- return;
- }
- }
- /* send key macro string */
-
- /*
- * PWP: note, we DON'T have to convert it to a Pascal string, 'cause
- * the macros are now stored as Pascal strings
- */
- writeps (tmpstr); /* send it to the line */
- if (duplex != 0)
- printps(termw,tmpstr); /* echo it locally */
- return;
- }
- for (i = 0; i < NUMOFMODS; i++) {
- /* shift what to look for into high byte */
- theModBits = modtable[i].modbits << 4;
- len = strlen (modtable[i].prefix);
-
- if ((theModBits || len) &&
- ((theModBits & modCode) == (theModBits & keyModifierMask))) {
- /* send prefix if there is one */
- if (len) {
- /* PWP: these are saved as Pascal strings now */
- BlockMove (modtable[i].prefix, tmpstr,
- (modtable[i].prefix[0] + 1));
- writeps (tmpstr); /* send it to the line */
- if (duplex != 0)
- printps(termw,tmpstr); /* echo it locally */
- }
-
- /*
- * get the unmodified ASCII code if the unmodify action bit is
- * active
- */
- if (theModBits & UnmodMask)
- c = DeModifyChar ((long) ((evt->message & myKeyCodeMask) >> 8),
- (long) (modCode & shiftKey));
- /* PWP: we pass through the shiftedness of this key */
- else
- c = evt->message & charCodeMask; /* otherwise get the
- * standard char */
-
- /* make an uppercase character if the caps action bit is active */
- if ((theModBits & CapsMask) && islower (c))
- c = toupper (c);
-
- /* make a control character if the control action bit is active */
- if (theModBits & CtrlMask)
- c &= ctrlCodeMask;
-
- /* PWP: for Meta characters (yes, I use Emacs) */
- if (theModBits & MetaMask)
- c |= metaOrBits;
-
- if (!checkescape(c))
- OutputChar (termw, c);
- return;
- } /* if */
- } /* for */
-
- /* get the ASCII code and send it */
- c = evt->message & charCodeMask;
- if (!checkescape(c))
- OutputChar(termw, c);
- } /* handle_char */
-
-
- /*
- * checkescape
- * Handle escape sequences in connected mode
- * Return TRUE if character used.
- */
- #define NKBUF 10
- checkescape (char c)
- {
- int x;
- static int esclevel = 0;
- static char *kbp, kbuf[NKBUF];
- extern int cmdmsk;
-
- switch (esclevel) {
- case 0: /* no escapes pending */
- if ((c & 0x7f) == escape) {
- esclevel++;
- return TRUE; /* we ate the char */
- }
- return FALSE; /* we did not process char */
-
- case 1: /* process escape command */
- if (doesc(c)) { /* if CMDQ */
- esclevel++;
- kbp = kbuf; /* preset buffer */
- *kbp++ = CMDQ;
- }
- else
- esclevel = 0;
- return TRUE; /* we ate the char */
-
- case 2: /* quoted backslash sequence */
- c &= cmdmsk;
- *kbp = c;
- if ((c != '\r') && (c != '\n')) {
- if (&kbuf[NKBUF-1] != kbp) /* if buffer not full */
- kbp++;
- return TRUE;
- }
- *kbp = 0;
- esclevel = 0;
-
- kbp = kbuf;
- x = xxesc(&kbp);
- if (x >= 0) {
- c = dopar(x);
- ttoc(c);
- } else { /* Invalid backslash code. */
- putchar(BEL);
- }
- return TRUE;
- }
- }
-
-
- /*
- * console_char
- * Handle keyboard events while not connected
- * Return TRUE if we inserted a character into the console buffer.
- *
- * THIS ROUTINE LIKELY NEEDS MORE WORK HANDLING SPECIAL CHARACTERS.
- *
- */
- console_char (struct termw *termw, EventRecord *evt)
- {
- short i;
- short len;
- short theCode;
- short modCode;
- short theModBits;
- char flags;
- char tmpstr[256];
- unsigned char c;
-
- /* (UoR) check for auto repeated keys */
- if ((termw->autorepeat == FALSE) && (evt->what == autoKey))
- return;
-
- ObscureCursor (); /* PWP: hide the cursor until next move */
-
- modCode = evt->modifiers & keyModifierMask;
- theCode = ((evt->message & myKeyCodeMask) >> 8) + (modCode >> 1);
-
- /* check for a special code for this key */
- if (BitTst (keytable, theCode)) {
- GetMacro (theCode, &flags, tmpstr); /* get the macrostring */
-
- if (flags) { /* check special flags */
- switch (flags) {
- case shortBreak:
- /* sendbreak (5); */
- return FALSE;
-
- case longBreak:
- /* sendbreak (70); */
- return FALSE;
-
- case leftArrowKey:
- /* do_arrow (leftARROW); */
- return FALSE;
-
- case rightArrowKey:
- /* do_arrow (rightARROW); */
- return FALSE;
-
- case upArrowKey:
- /* do_arrow (UPARROW); */
- return FALSE;
-
- case downArrowKey:
- /* do_arrow (DOWNARROW); */
- return FALSE;
-
- case keycomma:
- case keyminus:
- case keyperiod:
- /* there is no keyslash */
- case key0:
- case key1:
- case key2:
- case key3:
- case key4:
- case key5:
- case key6:
- case key7:
- case key8:
- case key9:
- /* do_keypad(flags - keycomma); */
- return FALSE;
-
- case keypf1:
- case keypf2:
- case keypf3:
- case keypf4:
- /* do_pfkey(flags - keypf1); */
- return FALSE;
-
- case keyenter:
- /* do_keyenter(); */
- return FALSE;
- }
- }
- /* send key macro string */
- writecb(tmpstr);
- return TRUE;
- }
-
- for (i = 0; i < NUMOFMODS; i++) {
- /* shift what to look for into high byte */
- theModBits = modtable[i].modbits << 4;
- len = strlen (modtable[i].prefix);
-
- if ((theModBits || len) &&
- ((theModBits & modCode) == (theModBits & keyModifierMask))) {
- /* send prefix if there is one */
- if (len) {
- /* PWP: these are saved as Pascal strings now */
- BlockMove (modtable[i].prefix, tmpstr,
- (modtable[i].prefix[0] + 1));
- writecb(tmpstr); /* put in console buffer */
- if (duplex != 0)
- printps(termw,tmpstr); /* echo it locally */
- }
-
- /*
- * get the unmodified ASCII code if the unmodify action bit is
- * active
- */
- if (theModBits & UnmodMask)
- c = DeModifyChar ((long) ((evt->message & myKeyCodeMask) >> 8),
- (long) (modCode & shiftKey));
- /* PWP: we pass through the shiftedness of this key */
- else
- c = evt->message & charCodeMask; /* otherwise get the
- * standard char */
-
- /* make an uppercase character if the caps action bit is active */
- if ((theModBits & CapsMask) && islower (c))
- c = toupper (c);
-
- /* make a control character if the control action bit is active */
- if (theModBits & CtrlMask)
- c &= ctrlCodeMask;
-
- /* PWP: for Meta characters (yes, I use Emacs) */
- if (theModBits & MetaMask)
- c |= metaOrBits;
-
- writecbc(c);
- return TRUE;
- } /* if */
- } /* for */
-
- /* get the ASCII code and send it */
- writecbc(evt->message & charCodeMask);
- return TRUE;
- }
-
-
- /****************************************************************************/
- /****************************************************************************/
- /****************************************************************************/
- /* general rectangle routines */
- /****************************************************************************/
-
-
-
- /****************************************************************************/
- /*
- * Routine makerect
- *
- * Make a rectangle in r starting on line lin and column col extending
- * numlin lines and numcol characters.
- *
- */
- /****************************************************************************/
- void
- makerect(struct termw *termw, Rect *r,int lin, int col, int numlin,
- int numcol)
- {
- r->top = lin * termw->lineheight + TOPMARGIN;
- r->left = col * termw->charwidth + LEFTMARGIN;
- r->bottom = r->top + numlin * termw->lineheight;
- r->right = r->left + numcol * termw->charwidth;
- } /* makerect */
-
- /* the (almost) inverse of makerect() */
- void
- recttocharpos(struct termw *termw, Rect *r, int *toplin_p, int *leftcol_p,
- int *botlin_p, int *rightcol_p)
- {
- /* Inverse of makerect(): find the bounding chars (rounding outward) */
- *toplin_p = (r->top - TOPMARGIN) / termw->lineheight;
- *botlin_p = (r->bottom - TOPMARGIN + termw->lineheight - 1)
- / termw->lineheight;
- *leftcol_p = (r->left - LEFTMARGIN) / termw->charwidth;
- *rightcol_p = (r->right - LEFTMARGIN + termw->charwidth - 1)
- / termw->charwidth;
-
- /* bounds limit it to the actual screen area */
- if (*toplin_p < 0) *toplin_p = 0;
- if (*botlin_p > termw->screensize) *botlin_p = termw->screensize;
- if (*leftcol_p < 0) *leftcol_p = 0;
- if (*rightcol_p > MAXCOL) *rightcol_p = MAXCOL;
- }
-
- /* (PWP) do what makerect does, then invert the rect */
- void
- invertchars(struct termw *termw, int lin, int col, int numlin, int numcol)
- {
- Rect r;
- r.top = lin * termw->lineheight + TOPMARGIN;
- r.left = col * termw->charwidth + LEFTMARGIN;
- r.bottom = r.top + numlin * termw->lineheight;
- r.right = r.left + numcol * termw->charwidth;
- InvertRect (&r);
- }
-
- /*
- * Figure out how wide this line could be. Not constant any more because of
- * double width lines.
- */
- int
- line_maxcol(struct termw *termw, int lin)
- {
- if (termw->line_attrs[lin] != VT_SNGL)
- return (MAXCOL / 2);
- else
- return (MAXCOL);
- }
-
- /****************************************************************************/
- /* Connect support routines */
- /****************************************************************************/
- void term_new_font (struct termw *termw)
- {
- FontInfo fi;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- SetFontLock(false);
- termw->font_is_locked = false;
-
- TextFont(termw->current_font); /* make sure to set this font */
- TextSize(termw->current_size);
-
- GetFontInfo (&fi);
-
- termw->lineheight = fi.ascent + fi.descent + fi.leading;
- termw->chardescent = fi.descent;
- /* termw->charwidth = fi.widMax; */
- termw->charwidth = CharWidth('W'); /* idea from NCSA telnet 2.3 */
-
- SetPort (savePort); /* there just has to be a better way */
- }
-
- /* consetup is called once at startup */
- struct termw *consetup (int boxid)
- {
- struct termw *termw;
- GrafPtr savePort;
- extern struct termw *termwl;
-
- termw = (struct termw *)malloc(sizeof(struct termw));
- if (!termw)
- macfatal("consetup: no memory for terminal window", 0);
- bzero((char *)termw, sizeof(struct termw));
- termw->next = termwl; /* add to list */
- termwl = termw;
- termw->current_font = VT100FONT;
- termw->current_size = 9;
- termw->scroll_drawn = -1; /* mark scroll bar invalid */
- termw->oldlin = -1;
- termw->from_lin = -1;
- termw->screensize = INIT_SCREENSIZE; /* number of lines on screen */
- termw->graphicsinset[0] = ASCII_SET;
- termw->graphicsinset[1] = ASCII_SET;
- termw->graphicsinset[2] = LAT1_SET;
- termw->graphicsinset[3] = LAT1_SET;
- termw->Gr_set = 1; /* (PWP) current chosen RH set */
- termw->old_Gl_set = -1; /* set to come back to after */
- /* single shift GL */
- termw->autowrap = TRUE; /* Autowrap on by default */
- termw->autorepeat = TRUE; /* (UoR) auto repeat flag */
- termw->dispcontchar = TRUE; /* do not show control characters */
- termw->blockcursor = TRUE; /* show block or underline cursor */
- termw->cursor_shown = TRUE; /* (PWP) show the cursor */
- termw->blinkcursor = TRUE; /* true if we make the cursor blink */
- termw->charflg = CF_OUTC; /* state variable */
-
- setWindowLoc(boxid);
- #ifdef notdef
- termw->window = GetNewWindow (boxid, (Ptr) &termw->terminalWRec,
- (WindowPtr) -1L);
- #else
- termw->window = GetNewWindow (boxid, (Ptr) 0L, (WindowPtr) -1L);
- #endif
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- PenMode (srcCopy); /* (PWP) was patXor */
- flushio (); /* Get rid of pending characters */
-
- termw->current_font = VT100FONT; /* (UoR) Set initial font to VT100 */
- termw->current_size = 9;
-
- if (termw->screeninvert)
- TextMode (srcBic);
- else
- TextMode (srcOr);
- TextFace (0); /* PWP: be safe. We allways stay like this */
-
- init_term(termw); /* Set up some terminal variables */
-
- /* reset the font (chosen above) */
- term_new_font(termw);
- /* doesn't change #lines, but size of a line has changed */
- grow_term_to(termw,termw->screensize);
-
- /* normal char mode, home cursor, clear screen, and save position */
- norm_home_clear_save(termw);
-
- cursor_draw(termw); /* (UoR) be sure to draw it */
-
- SetPort (savePort); /* there just has to be a better way */
-
- return termw;
- } /* consetup */
-
- void term_reset (struct termw *termw)
- {
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- PenMode (srcCopy); /* (PWP) was patXor */
- flushio (); /* Get rid of pending characters */
- screen_to_bottom(termw); /* slide the visible region to active area */
-
- termw->graphicsinset[0] = ASCII_SET;
- termw->graphicsinset[1] = GRAF_SET;
- termw->Gl_set = 0;
- termw->Gr_set = 1;
- termw->textstyle = 0;
- termw->current_style = 0;
- termw->draw_sing_chars = 0;
- termw->font_is_locked = FALSE;
- termw->screeninvert = FALSE; /* (UoR) inverted screen flag */
- termw->insert = FALSE;
- termw->newline = FALSE; /* (UoR) linefeed mode by default */
- termw->autowrap = TRUE; /* Autowrap on by default */
- termw->relorigin = FALSE; /* (UoR) relative origin off */
- termw->autorepeat = TRUE; /* (UoR) auto repeat flag */
- termw->appl_mode = FALSE; /* (PWP) keypad application mode */
- termw->curskey_mode = FALSE; /* (PWP) cursor key application mode */
- termw->smoothscroll = FALSE; /* do smooth scrolling (PWP: or not) */
- termw->scroll_amount = 0; /* no pending scroll */
- termw->refresh_amount = 0; /* no pending refresh */
- termw->dispcontchar = TRUE; /* do not show control characters */
- termw->blockcursor = TRUE; /* show block or underline cursor */
- termw->cursor_shown = TRUE; /* (PWP) show the cursor */
- termw->mouse_arrows = FALSE; /* mouse down in screen does arrow keys */
- termw->visible_bell = FALSE; /* true if we do blink instead of bell */
- termw->eightbit_disp = FALSE; /* default to 7 bits */
- termw->blinkcursor = TRUE; /* true if we make the cursor blink */
-
-
- termw->have_selection = FALSE; /* (PWP) we have no selected text */
-
- termw->saved_tlin = 0;
- termw->saved_blin = 0;
-
- termw->current_font = VT100FONT; /* (UoR) Set initial font to VT100 */
- termw->current_size = 9;
- termw->scroll_drawn = -1; /* mark scroll bar invalid */
-
- if (termw->screeninvert)
- TextMode (srcBic);
- else
- TextMode (srcOr);
- TextFace (0); /* PWP: be safe. We allways stay like this */
-
- /* reset the font (chosen above) */
- term_new_font(termw);
- /* doesn't change #lines, but size of a line has changed */
- grow_term_to(termw,termw->screensize);
-
- /* normal char mode, home cursor, clear screen, and save position */
- norm_home_clear_save(termw);
-
- cursor_draw(termw); /* (UoR) be sure to draw it */
-
- SetPort (savePort); /* there just has to be a better way */
- } /* consetup */
-
- /****************************************************************************/
- /****************************************************************************/
-
-
- /*************************************************/
- /* cursor drawing stuff */
- /*************************************************/
-
- Boolean cursor_rect (struct termw *termw, int line, int col, Rect *r)
- {
- /* if cursor not on screen */
- if (line - termw->display_topline >= termw->screensize)
- return FALSE;
-
- if (col >= 80) /* make it look like a VT100 */
- col = 79;
-
- /* Get character rectangle */
- makerect(termw,r, line - termw->display_topline, col, 1, 1);
- if (!termw->blockcursor) {
- r->top = r->bottom;
- r->bottom = r->top + 2;
- }
-
- return TRUE;
- } /* cursor_rect */
-
- void cursor_draw (struct termw *termw)
- {
- Rect r;
- GrafPtr savePort;
-
- if (!termw->cursor_shown) /* (PWP) not if we are hiding cursor */
- return;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- if (!termw->cursor_invert) {
- if (cursor_rect(termw,termw->curlin, termw->curcol, &r)) {
- if (termw->in_front) {
- InvertRect (&r);
- } else {
- PenMode (patXor);
- FrameRect (&r);
- PenMode (patCopy);
- }
- }
- }
-
- /* replace mouse cursor */
- if ((termw->oldlin >= 0) && (!termw->mousecurs_drawn)) {
- makerect(termw ,&r, termw->oldlin, termw->oldcol, 1, 1);
- PenMode (patXor);
- FrameRect (&r);
- PenMode (patCopy);
- termw->mousecurs_drawn = TRUE;
- }
-
- termw->cursor_invert = TRUE;
- termw->cur_drawn = TRUE;
-
- SetPort (savePort); /* there just has to be a better way */
- } /* cursor_draw */
-
-
- void cursor_erase (struct termw *termw)
- {
- Rect r;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- if (termw->cursor_invert) {
- if (cursor_rect(termw, termw->curlin, termw->curcol, &r)) {
- if (termw->in_front) {
- InvertRect (&r);
- } else {
- PenMode (patXor);
- FrameRect (&r);
- PenMode (patCopy);
- }
- }
- }
- /* remove mouse cursor */
- if ((termw->oldlin >= 0) && (termw->mousecurs_drawn)) {
- makerect(termw ,&r, termw->oldlin, termw->oldcol, 1, 1);
- PenMode (patXor);
- FrameRect (&r);
- PenMode (patCopy);
- termw->mousecurs_drawn = FALSE;
- }
-
- termw->cursor_invert = FALSE;
- termw->cur_drawn = FALSE;
-
- SetPort (savePort); /* there just has to be a better way */
- } /* cursor_erase */
-
- void flash_cursor (struct termw *termw)
- {
- register long tc;
- Rect r;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- tc = TickCount ();
- if (((tc - termw->last_flash) > MyCaretTime) ||
- (tc - termw->last_flash) < 0L) {
- termw->last_flash = tc;
-
- if (termw->cur_drawn) {
- if (cursor_rect(termw,termw->curlin, termw->curcol, &r)) {
- /* PWP: only blink if asked for */
- if (termw->blinkcursor && termw->in_front) {
- InvertRect (&r);
- termw->cursor_invert = !termw->cursor_invert;
- } else if (!termw->cursor_invert) {
- /* make sure that the cursor shows up */
- if (termw->in_front) {
- InvertRect (&r);
- } else {
- PenMode (patXor);
- FrameRect (&r);
- PenMode (patCopy);
- }
- termw->cursor_invert = TRUE;
- }
- }
- }
- }
-
- SetPort (savePort); /* there just has to be a better way */
- } /* flash_cursor */
-
-
- /****************************************************************************/
- /* PWP -- like waitasec(), but don't get any characters. Used for
- visable bell. */
- /****************************************************************************/
- waitnoinput ()
- {
- long ticks = 2, end_time;
-
- Delay (ticks, &end_time); /* pause for 1/30th second */
- } /* waitnoinput */
-
-
- /****************************************************************************/
- /* (UoR) get any characters, and pause for a while */
- /****************************************************************************/
- waitasec (struct termw *termw)
- {
- waitnoinput();
- inpchars(termw);
- } /* waitasec */
-
-
- /****************************************************************************/
- /* updateCursor -- taken from NCSA Telnet for the Macintosh, v 2.2 */
- /****************************************************************************/
- void updateCursor (struct termw *termw, int force, WindowPeek myfrontwindow)
- {
- static Point lastPoint;
- static int optwasdown = 0;
- Cursor *thisCursor;
- int optDown;
- KeyMap allthekeys; /* Someplace to put the keymap */
- char *cp_allthekeys = (char *) &allthekeys; /* $$$ HACK HACK */
- int newlin, newcol;
- Point MousePt;
- Rect r;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- GetMouse(&MousePt);
-
- GetKeys(allthekeys);
- optDown = cp_allthekeys[7] & 4; /* should be symbolic */
-
- if ( (!force) && (!in_background) && (MousePt == lastPoint) &&
- (optDown == optwasdown)) {
- SetPort (savePort);
- return;
- }
-
- if (force)
- lastCursor=0L;
-
- if (in_background) {
- lastCursor = 0L; /* allways force if in background */
- thisCursor = normcurs; /* default cursor shape */
- } else if (protocmd != 0) { /* if doing a transfer */
- thisCursor = watchcurs; /* in forground and doing a transfer */
- } else if (((myfrontwindow == termw->window) ||
- ((myfrontwindow == NIL) &&
- (FrontWindow() == termw->window))) &&
- PtInRect(MousePt, &termw->ScreenRect)) {
- if (termw->mouse_arrows || optDown) {
- newlin = (MousePt.v - TOPMARGIN) / termw->lineheight;
- newcol = (MousePt.h - LEFTMARGIN + termw->charwidth/2) /
- termw->charwidth;
-
- if ((termw->oldlin != newlin) || (termw->oldcol != newcol)) {
- PenMode (patXor); /* For FrameRect calls */
- if (termw->oldlin >= 0) { /* if old rectangle */
- if (termw->mousecurs_drawn) {
- makerect(termw,&r, termw->oldlin, termw->oldcol, 1, 1);
- FrameRect (&r);
- }
- } else { /* else if drawing for the first time */
- HideCursor ();
- }
-
- makerect(termw,&r, newlin, newcol, 1, 1);
- FrameRect (&r);
- PenMode (patCopy); /* reset to normal pen mode */
-
- termw->oldlin = newlin;
- termw->oldcol = newcol;
- termw->mousecurs_drawn = TRUE;
- }
- lastPoint=MousePt;
- optwasdown=optDown;
- SetPort (savePort); /* there just has to be a better way */
- return;
- } else {
- thisCursor = textcurs;
- }
- } else {
- thisCursor = normcurs; /* default cursor shape */
- }
-
- if (lastCursor!= thisCursor) {
- SetCursor(thisCursor);
- lastCursor = thisCursor;
- }
-
- lastPoint=MousePt;
- optwasdown=optDown;
-
- if (termw->oldlin >= 0) { /* if we hade drawn a movement outline */
- if (termw->mousecurs_drawn) {
- PenMode (patXor); /* For FrameRect calls */
- makerect(termw,&r, termw->oldlin, termw->oldcol, 1, 1);
- FrameRect (&r);
- }
-
- termw->oldlin = -1;
- termw->mousecurs_drawn = FALSE;
- ShowCursor ();
- PenMode (patCopy); /* reset to normal pen mode */
- }
-
- SetPort (savePort); /* there just has to be a better way */
- }
-
-
- /****************************************************************************/
- /* Put characters onto the actual screen */
- /****************************************************************************/
-
- static int to_mac_style[] = {
- normal, underline, italic, underline|italic,
- bold|condense, bold|condense|underline,
- bold|condense|italic, bold|condense|underline|italic
- };
-
- /****************************************************************************/
- /* flushbuf(termw) -- draw all the buffered characters on the screen */
- /****************************************************************************/
- void flushbuf (struct termw *termw)
- {
- register int i, scrl_amt;
-
- if (termw->out_maxcol == 0)
- return; /* Nothing to flush */
-
- if (to_printer) { /*JAO*/
- for (i = termw->out_mincol; i < termw->out_maxcol; i++) {
- (*hPrintBuffer)[lPrintBufferAt++] =
- termw->scr[termw->curlin+termw->display_topline][i];
- if (lPrintBufferAt == lPrintBufferSize)
- lPrintBufferAt = 0L;
- lPrintBufferChars++;
- if (lPrintBufferChars == 1L)
- updatepstat();
- if (lPrintBufferChars == lPrintBufferSize) {
- overflowingDialog = GetNewDialog(OVERFLOWINGBOXID, NILPTR,
- (WindowPtr) - 1);
- DrawDialog(overflowingDialog);
- break; /* PWP */
- }
- }
- }
-
- if (!to_screen) {
- termw->out_maxcol = 0; /* Say no more chars to output */
- return; /*JAO*/
- }
-
- /* save because flushscroll() resets scroll_amount */
- scrl_amt = termw->scroll_amount;
- #ifdef COMMENT
- if (scrl_amt) {
- /*
- * If we have pending scrolling, and we are about to draw outside
- * of the region that will be refreshed when the scrolling happens,
- * do the scrolling now.
- */
- if ((termw->refresh_amount < 0) &&
- ((termw->curlin < termw->saved_blin + termw->refresh_amount)
- || (termw->curlin > termw->saved_blin)))
- {
- flushscroll(termw);
- }
- else if ((termw->refresh_amount > 0) &&
- ((termw->curlin < termw->saved_tlin)
- || (termw->curlin
- > termw->saved_tlin + termw->refresh_amount)))
- {
- flushscroll(termw);
- }
- else
- {
- termw->out_maxcol = 0; /* Say no more chars to output */
- return;
- }
- }
- #endif /* COMMENT */
-
- if (scrl_amt)
- flushscroll(termw);
-
- if (termw->have_selection)
- maybe_nuke_selection (termw, termw->curlin, termw->curlin);
-
- if (!termw->out_maxcol) /* if already drawn this line, return */
- return;
-
- /*
- * PWP: Why have two routines to do the same thing? I centralized
- * all the font crap into draw_line_w_attrs so I didn't need
- * to keep track of code here too. Side benifit -- we can nuke
- * the outbuf array.
- *
- * Note that in draw_line_w_attrs(), the left and right columns are
- * SCREEN columns, not virtual buffer columns. Theses are usually
- * the same, unless we happen to be drawing onto a double-width line.
- */
- if (termw->line_attrs[termw->curlin] == VT_SNGL) {
- /* single-width (normal) line */
- draw_line_w_attrs(termw, termw->curlin + termw->display_topline,
- termw->curlin, termw->out_mincol, termw->out_maxcol,
- (scrl_amt == 0));
- } else {
- /* line with double width characters */
- draw_line_w_attrs(termw, termw->curlin + termw->display_topline,
- termw->curlin, 2 * termw->out_mincol,
- 2 * termw->out_maxcol, (scrl_amt == 0));
- }
- termw->out_maxcol = 0; /* Say no more chars to output */
- } /* flushbuf */
-
- /****************************************************************************/
- /* set_style(termw, style)
- - set the correct stuff for displaying chars in style */
- /****************************************************************************/
- void set_style (struct termw *termw, int style)
- {
- int m_sty, m_font;
- static int o_sty = 0, o_font = 0;
-
- if (style == termw->current_style)
- return;
- termw->current_style = style;
-
- m_sty = to_mac_style[style & STY_MSTY];
- m_font = ((style & STY_FONT) >> 3) + termw->current_font;
- termw->draw_sing_chars = ((style & VT_BLINK)
- || (CharWidth('W')!=CharWidth('i'))
- || (!RealFont(termw->current_font,
- termw->current_size)));
- /* printerr("draw_sing_chars == ", draw_sing_chars); */
-
- if (!have_128roms && (m_sty & bold)) { /* if on an old mac and bolding */
- if (m_font == VT100FONT) {
- m_font = VT100BOLD;
- m_sty &= ~(bold|condense);
- } else {
- termw->draw_sing_chars = 1;
- }
- }
-
- if (m_font != o_font) {
- TextFont (m_font); /* new font */
- o_font = m_font;
- }
- if (m_sty != o_sty) {
- TextFace (m_sty); /* new text face */
- o_sty = m_sty;
- }
- }
-
- /****************************************************************************
- * draw_line_w_attrs() -- draw the line including all character attributes
- * that is in the terminal buffer at line "lin" onto the screen at vertical
- * character offset "v", in as little time as possible.
- *
- * It seems to speed things up just a tad to skip leading and trailing
- * whitespace on the line, so we can draw only the characters in the middle.
- * On the other hand, it doesn't save any time to find the individual words
- * and draw just those. Likewise, if we have to draw the line one character
- * at a time it is really slow.
- *
- * Perhaps a later version of Kermit could take the current fonts and build
- * custom set of fixed width fonts (a'la BitFont), and then use that to draw
- * characters onto the screen.
- *
- * Another later addition could be correct handling of double width and double
- * height characters, by drawing the characters into an off-screen bitmap,
- * and then using CopyBits to stretch the characters to fit.
- */
-
- void draw_line_w_attrs (struct termw *termw, register int lin, register int v,
- register int l_col, register int r_col,
- int must_drawblanks)
- {
- register int o, i, j, sty;
- register char *cp, *ap, *line_ch, *line_at;
- register int min, max;
- register int lines_attrs;
- int orig_l_col;
- Rect r;
-
- if (!termw)
- DebugStr("\ptermw == NULL");
-
- /* this routine CAN be called with scrolling_region non-zero */
-
- /* bounds limit the min and max columns */
- if (l_col < 0) l_col = 0;
- if (l_col > MAXCOL) l_col = MAXCOL;
- if (r_col < 0) r_col = 0;
- if (r_col > MAXCOL) r_col = MAXCOL;
-
- /* if nothing to do, don't bother */
- if ((r_col == 0) || (l_col == r_col))
- return;
-
- /***** I shouldn't have to put this here! *****/
- if (termw->screeninvert) {
- BackPat(qd.black);
- PenPat(qd.white);
- TextMode (srcBic);
- } else {
- BackPat(qd.white);
- PenPat(qd.black);
- TextMode (srcOr);
- }
-
- if ((v < 0) || (v > termw->screensize))
- printerr("draw_line_w_attrs, v out of range:", v);
-
- line_ch = termw->scr[lin];
- line_at = termw->scr_attrs[lin];
- lines_attrs = (int) termw->line_attrs[lin];
- if (lines_attrs != VT_SNGL) {
- /* double width lines have half as many characters (duh!) */
- orig_l_col = l_col;
- l_col /= 2;
- r_col = (r_col + 1) / 2; /* round out to next highest */
- }
-
- /*
- * find the last character that is not a plain space character
- */
- sty = 0; /* the style for normal blank space */
- cp = line_ch + r_col-1;
- ap = line_at + r_col-1;
- for (max = r_col-1; max >= l_col; max--) {
- /* PWP: we should never see a NUL in the line here */
- if ((*cp-- != ' ') || (*ap-- != sty))
- break;
-
- }
- max++; /* point to one after the last non-space character */
- if (max > r_col) max = r_col;
-
- /*
- * find the first character that is not a plain space character
- */
- sty = 0; /* the style for normal blank space */
- cp = line_ch + l_col;
- ap = line_at + l_col;
- for (min = l_col; min < max; min++) {
- /* PWP: we should never see a NUL in the line here */
- if ((*cp++ != ' ') || (*ap++ != sty))
- break;
- }
-
- /* If there is anything to erase, erase it */
- if (must_drawblanks) {
- if (lines_attrs == VT_SNGL)
- makerect(termw,&r, v, l_col, 1, r_col-l_col);
- else
- makerect(termw,&r, v, (2 * l_col), 1, 2 * (r_col-l_col));
- EraseRect (&r);
- }
-
- /* A slight speedup -- tell the Mac not to remove this font from RAM */
- if (!termw->font_is_locked) {
- SetFontLock(true);
- termw->font_is_locked = true;
- }
-
-
- if (lines_attrs == VT_SNGL) {
- /*
- * loop through all the characters up to max, looking for the longest
- * string of characters all of the same style. Draw them, switch
- * styles, and repeat until max.
- */
- sty = line_at[min];
- o = min;
- i = min;
- while (i <= max) {
- /* if this style != current style */
- if ((line_at[i] != sty) || (i == max)) {
- if (sty != termw->current_style)
- set_style(termw, sty);
-
- if (termw->draw_sing_chars) {
- /*
- * We can't just increment o here because we may need
- * it to correctly draw the inverse video rect (below).
- */
- for (j = o, cp = line_ch + o; j < i; j++, cp++) {
- MOVETOCHAR(j, v);
- DrawChar((short) (*cp & 0377));
- }
- } else { /* non-blinking */
- MOVETOCHAR(o, v);
- DrawText (line_ch, (short) o, (short) i-o);
- /* Output this part */
- }
-
- if (sty & VT_INVERT) {
- makerect(termw,&r, v, o, 1, i-o);
- InvertRect (&r);
- }
-
- o = i; /* now left extent == current */
- sty = line_at[i]; /* new current style */
- }
- i++;
- }
- } else {
- #ifdef COMMENT_DOES_NOT_WORK
- RgnHandle clip_rgn = NewRgn();
- Rect dest_r;
- GrafPtr oldPort;
- GrafPort offScreen;
-
- /* allocate our off-screen bitmap */
- GetPort(&oldPort);
- OpenPort(&offScreen);
- SetPort(oldPort);
-
- /* Make our off-screen bitmap the size of one line */
- offScreen.portRect.top = 0;
- offScreen.portRect.left = 0;
- offScreen.portRect.bottom = termw->lineheight;
- offScreen.portRect.right = termw->charwidth;
-
- /* rowBytes is the size of a row, rounded up to an even number */
- /* of bytes */
- offScreen.portBits.rowBytes = (((offScreen.portBits.bounds.right
- - offScreen.portBits.bounds.left) + 15) >> 4) << 1;
-
- /* number of bytes in BitMap is rowBytes * number of rows */
- /* this calculation must be down with longs */
- offScreen.portBits.baseAddr = NewPtr((long) offScreen.portBits.rowBytes
- * (long) (offScreen.portBits.bounds.bottom
- - offScreen.portBits.bounds.top));
-
- if (!offScreen.portBits.baseAddr) /* we didn't get the memory */
- return; /* just forget it */
-
- /*
- * We are drawing double-width (and maybe double height) chars.
- *
- * First, draw the line normally, but starting at the
- * real position of original the original value of l_col.
- */
- SetPort (&offScreen);
- BackPat(qd.white);
- PenPat(qd.black);
- TextMode (srcOr);
- EraseRect(&qd.thePort->portRect); /* erase just in case */
-
- o = 0;
- cp = line_ch + min;
- ap = line_at + min;
- for (i = min; i <= max; i++) {
-
- MoveTo ((o * termw->charwidth),
- (termw->lineheight - termw->chardescent));
- DrawChar((short) (*cp & 0377));
- if (*ap & VT_INVERT) {
- makerect(termw,&r, v, o, 1, 1);
- InvertRect (&r);
- }
- o++;
- cp++;
- ap++;
- }
-
- /* set the output port back to the screen */
- SetPort(oldPort);
-
- /* Next, stretch the characters using a CopyBits() */
- /* find the clipping region */
- makerect(termw, &r, v, (2 * l_col), 1, 2 * (r_col-l_col));
- RectRgn (clip_rgn, &r);
- FillRgn (clip_rgn, qd.gray);
-
- /* compute the source rect (where we just drew characters into) */
- r = offScreen.portRect;
- r.right = (max-min+1) * termw->charwidth;
-
- /*
- * Compute the dest rect. This also defines how we stretch
- * the characters out to be double width.
- */
-
- if (lines_attrs == VT_DBLH_T) {
- makerect(termw, &dest_r, v, ((2 * l_col) + (min - l_col)),
- 2, (2 * (max-min+1)));
- } else if (lines_attrs == VT_DBLH_B) {
- makerect(termw, &dest_r, (v-1), ((2 * l_col) + (min - l_col)),
- 2, (2 * (max-min+1)));
- } else { /* lines_attrs == VT_DBLW */
- makerect(termw, &dest_r, v, ((2 * l_col) + (min - l_col)),
- 1, (2 * (max-min+1)));
- }
-
- makerect(termw, &dest_r, v, ((2 * l_col) + (min - l_col)),
- 1, (max-min+1));
-
- /* now stretch those bits */
- CopyBits (&offScreen.portBits, &qd.thePort->portBits,
- &offScreen.portRect, &dest_r,
- ((termw->screeninvert) ? notSrcCopy : srcCopy), clip_rgn);
-
- /* clean up */
- DisposeRgn(clip_rgn);
- ClosePort(&offScreen);
- #endif /* COMMENT_DOES_NOT_WORK */
-
- /* draw the double width line as double spaced characters */
- o = min;
- cp = line_ch + min;
- ap = line_at + min;
- for (i = min; i <= max; i++) {
- if (*ap != termw->current_style)
- set_style(termw, *ap);
- MOVETOCHAR((2 * o), v);
- DrawChar((short) (*cp & 0377));
- if (*ap & VT_INVERT) {
- makerect(termw,&r, v, (2 * o), 1, 2);
- InvertRect (&r);
- }
- o++;
- cp++;
- ap++;
- }
- }
- } /* draw_line_w_attrs() */
-
-
- /****************************************************************************/
- /****************************************************************************/
- void scroll_term (struct termw *termw)
- {
- register int new_topline, delta, lin, i;
- int fl, fc, tl, tc;
- Rect r; /* cannot be register */
-
- new_topline = termw->screensize - termw->display_totlines +
- GetCtlValue (termw->t_vscroll);
- if ((new_topline > 0) ||
- (new_topline < termw->screensize - MAX_SCREENSIZE)) {
- printerr("BUG: in scroll_term(), new_topline out of range:",
- new_topline);
- return;
- }
- if ((delta = (termw->display_topline - new_topline)) == 0)
- return; /* we didn't move */
-
- makerect(termw,&r, 0, 0, termw->screensize, MAXCOL);
-
- /* if whole screen */
- if ((delta >= termw->screensize) || (-delta >= termw->screensize)) {
- EraseRect(&r);
-
- lin = new_topline; /* new top line */
- for (i = 0; i < termw->screensize; i++) {
- draw_line_w_attrs(termw, lin, i, 0, MAXCOL, 0);
- lin++;
- }
- termw->display_topline = new_topline;
-
- if (termw->have_selection)
- invert_text(termw,
- termw->from_lin,
- termw->from_col,
- termw->to_lin,
- termw->to_col);
-
- return; /* we are done */
- }
-
- /* if we get here, we are not doing the whole screen */
- ScrollRect (&r, 0, delta * termw->lineheight, dummyRgn);
-
- if (delta > 0) { /* scrolling down (pushing top arrow) */
- lin = new_topline; /* new top line */
- for (i = 0; (i < delta) && (i < termw->screensize); i++) {
- draw_line_w_attrs(termw, lin, i, 0, MAXCOL, 0);
- lin++;
- }
- termw->display_topline = new_topline;
-
- if (termw->have_selection &&
- (termw->from_lin < termw->display_topline + delta) &&
- (termw->to_lin >= termw->display_topline)) {
- if (termw->from_lin < termw->display_topline) {
- fl = termw->display_topline;
- fc = 0;
- } else {
- fl = termw->from_lin;
- fc = termw->from_col;
- }
- if (termw->to_lin >= termw->display_topline + delta) {
- tl = termw->display_topline + delta - 1;
- tc = MAXCOL;
- } else {
- tl = termw->to_lin;
- tc = termw->to_col;
- }
- invert_text(termw, fl, fc, tl, tc);
- }
- } else {
- /* scrolling up (pushing bottom arrow) */
- /* one past old bottom line*/
- lin = termw->display_topline + termw->screensize;
- /*********** PWP: delta is negative here ****************/
- i = termw->screensize + delta;
- if (i < 0) i = 0; /* bounds */
- while (i < termw->screensize)
- draw_line_w_attrs(termw, lin++, i++, 0, MAXCOL, 0);
- termw->display_topline = new_topline;
-
- if (termw->have_selection &&
- (termw->from_lin <
- (termw->display_topline + termw->screensize)) &&
- (termw->to_lin >=
- (termw->display_topline + termw->screensize + delta))) {
-
- /*
- * If selection is partially off the top,
- * clip display of region at top
- */
- if (termw->from_lin <
- termw->display_topline + termw->screensize + delta) {
- fl = termw->display_topline + termw->screensize + delta;
- fc = 0;
- } else {
- fl = termw->from_lin;
- fc = termw->from_col;
- }
-
- /*
- * If selection is partially off the top,
- * clip display of region at top.
- */
- if (termw->to_lin >= termw->display_topline + termw->screensize) {
- tl = termw->display_topline + termw->screensize - 1;
- tc = MAXCOL;
- } else {
- tl = termw->to_lin;
- tc = termw->to_col;
- }
-
- invert_text(termw, fl, fc, tl, tc);
- }
- }
- }
-
- static pascal void
- doscroll (WHICHCONTROL, THECODE)
- ControlHandle WHICHCONTROL;
- short THECODE;
- {
- register int amount = 0, val, max;
- struct termw *termw;
-
- if (FrontWindow() == ctermw->window)
- termw = ctermw ;
- else if (FrontWindow() == ttermw->window)
- termw = ttermw ;
- else
- return;
-
- if (THECODE == inUpButton)
- amount = -1;
- if (THECODE == inDownButton)
- amount = 1;
- if (amount == 0)
- return;
- val = GetCtlValue (WHICHCONTROL) + amount;
- max = GetCtlMax (WHICHCONTROL);
- if ((val >= 0) && (val <= max)) {
- SetCtlValue (WHICHCONTROL, val);
- scroll_term(termw);
- }
- } /* doscroll */
-
-
- /****************************************************************************/
- /* we move the displayed region to the bottom when we recieve characters */
- /****************************************************************************/
-
- screen_to_bottom (struct termw *termw)
- {
- if (termw->display_topline != toplin) {
- SetCtlValue (termw->t_vscroll,
- termw->display_totlines - termw->screensize);
- scroll_term(termw);
- }
- }
-
- /****************************************************************************/
- /* update_vscroll - adjust the scaling of the vertical scroll bar, or */
- /* disable it if we havn't saved anything back yet */
- /****************************************************************************/
- update_vscroll (struct termw *termw)
- {
- short s;
-
- s = termw->display_totlines-termw->screensize;
-
- if (s != GetCtlMax (termw->t_vscroll))
- SetCtlMax (termw->t_vscroll, s);
-
- if (s != GetCtlValue (termw->t_vscroll))
- SetCtlValue (termw->t_vscroll, s);
-
- if (termw->in_front && termw->display_totlines > termw->screensize) {
- if (termw->scroll_drawn != 1) {
- HiliteControl (termw->t_vscroll, 0);
- termw->scroll_drawn = 1;
- }
- } else {
- if (termw->scroll_drawn != 0) {
- HiliteControl (termw->t_vscroll, 255);
- termw->scroll_drawn = 0;
- }
- }
- }
-
- /****************************************************************************/
- /****************************************************************************/
- void t_pagescroll (struct termw *termw, int code, int amount,
- ControlHandle ctrlh)
- {
- Point myPt;
- register int val, max;
-
- max = GetCtlMax (ctrlh);
- val = GetCtlValue (ctrlh);
-
- do {
- GetMouse (&myPt);
- if (TestControl (ctrlh, myPt) != code)
- continue;
-
- val += amount;
- if (val < 0)
- val = 0;
- if (val > max)
- val = max;
- SetCtlValue (ctrlh, val);
- scroll_term(termw);
- } while (StillDown ());
- } /* pagescroll */
-
-
- termmouse (struct termw *termw, EventRecord *evt)
- {
- int actrlcode;
- ControlHandle acontrol;
- GrafPtr savePort;
-
- GetPort (&savePort); /* save the current port */
- SetPort (termw->window);
-
- GlobalToLocal (&evt->where);/* convert to local */
- if (termw->mouse_arrows || (evt->modifiers & optionKey)) {
- /* In terminal content? */
- if (PtInRect (evt->where, &termw->ScreenRect)) {
- mouse_cursor_move(termw, evt);
- SetPort (savePort); /* restore previous port */
- return; /* yes, do mouse stuff */
- }
- }
- cursor_erase(termw);
- actrlcode = FindControl (evt->where, termw->window, &acontrol);
- switch (actrlcode) {
- case inUpButton:
- case inDownButton:
- (void) TrackControl (acontrol, evt->where, (ProcPtr) doscroll);
- break;
-
- case inPageUp:
- t_pagescroll (termw, actrlcode, -(termw->screensize/2), acontrol);
- break;
-
- case inPageDown:
- t_pagescroll (termw, actrlcode, (termw->screensize/2), acontrol);
- break;
-
- case inThumb:
- (void) TrackControl (acontrol, evt->where, (ProcPtr) NIL);
- scroll_term(termw);
- break;
-
- case 0: /* in the window content itself */
- /* $$$ SHOULD DO SOMETHING ABOUT DOUBLE CLICKS HERE!! */
- mouse_region_select(termw, evt);
- break;
- }
- /* MOVETOCHAR(termw->curcol, termw->curlin - termw->display_topline); */
- cursor_draw(termw);
- SetPort (savePort); /* restore previous port */
- }
-
-
- /*
- * dir is 'A' (up), 'B' (down), 'C' (right), or 'D' (left)
- */
- void do_arrow(struct termw *termw, unsigned char dir)
- {
- OutputChar(termw, '\033'); /* ESC */
- if (termw->curskey_mode)
- OutputChar(termw, 'O'); /* SS3 */
- else
- OutputChar(termw, '['); /* CSI */
- OutputChar(termw, dir);
- }
-
- /* char to send is n + ',' */
- void do_keypad (struct termw *termw, int n)
- {
- if (termw->appl_mode) {
- OutputChar(termw, '\033'); /* ESC */
- OutputChar(termw, 'O'); /* SS3 */
- OutputChar(termw, (unsigned char) n + 'l');
- } else {
- OutputChar(termw, (unsigned char) n + ','); /* normal digit or glyph */
- }
- }
-
- /* pf1 == 0 ... pf4 == 3 */
- void do_pfkey(struct termw *termw, int n)
- {
- OutputChar(termw, '\033'); /* ESC */
- OutputChar(termw, 'O'); /* SS3 */
- OutputChar(termw, (unsigned char) n + 'P');
- }
-
- void do_keyenter(struct termw *termw)
- {
- if (termw->appl_mode) {
- OutputChar(termw, '\033'); /* ESC */
- OutputChar(termw, 'O'); /* SS3 */
- OutputChar(termw, 'M');
- } else {
- OutputChar(termw, '\015');
- }
- }
-
- void mouse_cursor_move (struct termw *termw, EventRecord *evt)
- {
- int mouselin;
- int mousecol;
- int tempcol;
- int templin;
- int i;
- Point MousePt;
-
- MousePt = evt->where;
- mouselin = (MousePt.v - TOPMARGIN) / termw->lineheight;
- mousecol = (MousePt.h - LEFTMARGIN + termw->charwidth/2) /
- termw->charwidth;
- tempcol = termw->curcol;
- templin = termw->curlin;
-
- if (mousecol < tempcol)
- for (i = tempcol; i > mousecol; i--) {
- do_arrow (termw, leftARROW);
- waitasec (termw);
- /* If tabs are used, we may go too far, so end loop */
- if (termw->curcol <= mousecol)
- i = mousecol;
- }
-
- if (mouselin < templin)
- for (i = templin; i > mouselin; i--) {
- do_arrow (termw, UPARROW);
- waitasec (termw);
- }
-
- else if (mouselin > templin)
- for (i = templin; i < mouselin; i++) {
- do_arrow (termw, DOWNARROW);
- waitasec (termw);
- }
-
- if (termw->curlin == mouselin)
- tempcol = termw->curcol; /* for short lines */
-
- if (tempcol < mousecol)
- for (i = tempcol; i < mousecol; i++) {
- do_arrow (termw, rightARROW);
- waitasec (termw);
- /* If tabs are used, we may go too far, so end loop */
- if (termw->curcol >= mousecol)
- i = mousecol;
- }
- } /* mouse_cursor_move */
-
- void invert_text(struct termw *termw,
- int from_lin,
- int from_col,
- int to_lin,
- int to_col)
- {
- int t;
-
- if (from_lin > to_lin) { /* make from < to */
- t = to_lin;
- to_lin = from_lin;
- from_lin = t;
- t = to_col;
- to_col = from_col;
- from_col = t;
- }
-
- /* if we are doing double width chars, the columns are twice as wide */
- if (termw->line_attrs[from_lin] != VT_SNGL)
- from_col *= 2;
- if (termw->line_attrs[to_lin] != VT_SNGL)
- to_col *= 2;
-
- from_lin -= termw->display_topline; /* convert to screen coords */
- if (from_lin < 0) {
- from_lin = 0;
- from_col = 0;
- }
-
- /* if down out of sight, forget it */
- if (from_lin >= termw->screensize)
- return;
-
- to_lin -= termw->display_topline; /* convert to screen coords */
-
- if (to_lin < 0) /* if up out of sight, forget it */
- return;
-
- if (to_lin >= termw->screensize) {
- to_lin = termw->screensize-1;
- to_col = MAXCOL;
- }
-
- if (from_lin == to_lin) { /* if only one line */
- if (from_col > to_col) {
- t = to_col;
- to_col = from_col;
- from_col = t;
- }
-
- if (from_col != to_col) /* then invert the characters in between */
- invertchars(termw, from_lin, from_col, 1, to_col - from_col);
- } else {
- if (from_col < MAXCOL)
- invertchars(termw, from_lin, from_col, 1, MAXCOL - from_col);
- t = to_lin - from_lin - 1;
- if (t > 0)
- invertchars(termw, from_lin+1, 0, t, MAXCOL);
- if (to_col > 0)
- invertchars(termw, to_lin, 0, 1, to_col);
- }
- }
-
-
- int typeof_char(unsigned char c)
- {
- if ((c == ' ') || (c == '\240'))
- return (0); /* whitespace char */
-
- if (((c >= '0') && (c <= '9'))
- || ((c >= 'A') && (c <= 'Z'))
- || ((c >= 'a') && (c <= 'z'))
- || ((c >= '\300') && (c <= '\377') && (c != '\327') && (c != '\367'))
- || ((c >= '\271') && (c <= '\276') && (c != '\273'))
- || (c == '\262') || (c == '\263') || (c == '\252'))
- return (1); /* alpha-numeric char */
-
- return (2); /* printing, non-alphanum char */
- }
-
-
- int all_spaces (struct termw *termw, register int r, register int c)
- {
- register int i;
-
- for (i = c; i < line_maxcol(termw, r); i++)
- if ((termw->scr[r][i] != ' ')
- || (termw->scr_attrs[r][i] != 0))
- return (0); /* found a non-space */
-
- return (1); /* everything was spaces */
- }
-
-
- void point_to_mouse_low_high (struct termw *termw,
- Point *MousePt_p,
- int n_clicks,
- int *mouselin_p,
- int *mousecol_p,
- int *mousecol_lp,
- int *mousecol_hp)
- {
- int real_lin, real_col;
- int ch_type, ch_attr;
- int i;
-
- real_lin = (MousePt_p->v-TOPMARGIN) / termw->lineheight +
- termw->display_topline;
- if (real_lin < termw->display_topline)
- real_lin = termw->display_topline;
- if (real_lin >= termw->display_topline + termw->screensize)
- real_lin = termw->display_topline + termw->screensize-1;
-
- *mouselin_p = real_lin;
-
- real_col = (MousePt_p->h - LEFTMARGIN + termw->charwidth/2) /
- termw->charwidth;
- if (real_col < 0) real_col = 0;
- if (real_col > MAXCOL) /* this is a real, not virtual, column */
- real_col = MAXCOL;
-
- /* if on a double-width line, all columns are twice as wide */
- if (termw->line_attrs[real_lin] != VT_SNGL)
- real_col /= 2;
-
- /*
- * We spoof things a bit here -- if the rest of the line is all blanks,
- * then we treat it as a single character (CRLF, really), and pretend
- * that the user clicked the mouse in the first blank character after all
- * text.
- */
- if (all_spaces(termw,real_lin, real_col))
- {
- for (i = real_col; i >= 0; i--)
- if ((termw->scr[real_lin][i] != ' ')
- || (termw->scr_attrs[real_lin][i] != 0))
- break;
- real_col = i+1;
- if (real_col < 0) real_col = 0;
- if (real_col > line_maxcol(termw, real_lin))
- real_col = line_maxcol(termw, real_lin);
- }
-
- *mousecol_p = real_col;
-
- if (n_clicks == 0) /* if a SINGLE click */
- {
- *mousecol_lp = real_col;
- *mousecol_hp = real_col;
- }
- else if (n_clicks == 1) /* if a DOUBLE click */
- {
- ch_type = typeof_char (termw->scr[real_lin][real_col]);
- ch_attr = termw->scr_attrs[real_lin][real_col];
- for (i = real_col-1; i >= 0; i--)
- /* if a different type */
- if ((typeof_char (termw->scr[real_lin][i]) != ch_type)
- /* or colored different */
- || (termw->scr_attrs[real_lin][i] != ch_attr))
- /* then it isn't the same kind of char */
- break;
- *mousecol_lp = i+1;
- for (i = real_col+1; i < line_maxcol(termw, real_lin); i++)
- /* if a different type */
- if ((typeof_char (termw->scr[real_lin][i]) != ch_type)
- /* or colored different */
- || (termw->scr_attrs[real_lin][i] != ch_attr))
- /* then it isn't the same kind of char */
- break;
- *mousecol_hp = i;
- }
- else /* a TRIPLE click */
- {
- *mousecol_lp = 0;
- *mousecol_hp = line_maxcol(termw, real_lin);
- }
- }
-
-
- void mouse_region_select (struct termw *termw, EventRecord *evt)
- {
- int mouselin;
- int mousecol_l, mousecol_h, real_mousecol;
- int i, shift, sval, smax;
- int old_from_lin, old_from_col, old_to_lin, old_to_col;
- Point MousePt;
- /* used for double-click determination */
- static Point prev_mouse_point = {0, 0};
- static long prev_mouse_up = 0L;
- static int n_clicks_here = 0;
-
- MousePt = evt->where;
-
- /* if no selection, then a shift drag is just a drag */
- if (termw->have_selection)
- shift = (evt->modifiers) & shiftKey;
- else
- shift = 0;
-
- if (((evt->when - prev_mouse_up) <= GetDblTime())
- && (ABS(MousePt.v - prev_mouse_point.v) < termw->lineheight)
- && (ABS(MousePt.h - prev_mouse_point.h) < termw->charwidth))
- n_clicks_here = (n_clicks_here + 1) % 3;
- else
- n_clicks_here = 0; /* just one click */
-
- prev_mouse_point = MousePt; /* save for next time */
- prev_mouse_up = TickCount (); /* save when the mouse went up */
-
- /* if not adding to region, remove old one */
- if (!shift && termw->have_selection)
- invert_text(termw,
- termw->from_lin,
- termw->from_col,
- termw->to_lin,
- termw->to_col);
-
-
- point_to_mouse_low_high(termw,&MousePt, n_clicks_here, &mouselin,
- &real_mousecol, &mousecol_l, &mousecol_h);
-
- if (shift) {
- /*
- * Swap from_* and to_* if closer to from. This sets the further-away
- * side as the anchor, and the closer one as the part we are changing.
- *
- * We aren't taking into account any double width lines here, but that
- * should be OK anyway (I hope)
- */
- if (ABS((MAXCOL * termw->from_lin + termw->from_col) -
- (MAXCOL * mouselin + real_mousecol)) <
- ABS((MAXCOL * termw->to_lin + termw->to_col)
- - (MAXCOL * mouselin + real_mousecol))) {
- i = termw->to_lin;
- termw->to_lin = termw->from_lin;
- termw->from_lin = i;
- i = termw->to_col;
- termw->to_col = termw->from_col;
- termw->from_col = i;
- }
- } else {
- termw->from_lin = mouselin;
- termw->from_col = mousecol_l;
- termw->to_lin = mouselin;
- termw->to_col = mousecol_h;
-
- /* Select the text if a double or triple click. */
- if (termw->from_col != termw->to_col)
- invert_text(termw,
- termw->from_lin,
- termw->from_col,
- termw->to_lin,
- termw->to_col);
- }
- /* save in case we have to swap which point is the anchor */
- old_from_lin = termw->from_lin;
- old_from_col = termw->from_col;
- old_to_lin = termw->to_lin;
- old_to_col = termw->to_col;
-
- while (StillDown()) {
- GetMouse(&MousePt);
- point_to_mouse_low_high(termw,&MousePt, n_clicks_here, &mouselin,
- &real_mousecol, &mousecol_l, &mousecol_h);
-
- /*
- * If above or below screen, auto-scroll the slider and select more.
- */
-
- if (mouselin < termw->display_topline) {
- sval = GetCtlValue (termw->t_vscroll) - 1;
- smax = GetCtlMax (termw->t_vscroll);
- if ((sval >= 0) && (sval <= smax)) {
- SetCtlValue (termw->t_vscroll, sval);
- scroll_term(termw);
- }
- mouselin = termw->display_topline;
- real_mousecol = 0;
-
- } else if (mouselin >= termw->display_topline + termw->screensize) {
- sval = GetCtlValue (termw->t_vscroll) + 1;
- smax = GetCtlMax (termw->t_vscroll);
- if ((sval >= 0) && (sval <= smax)) {
- SetCtlValue (termw->t_vscroll, sval);
- scroll_term(termw);
- }
- mouselin = termw->display_topline + termw->screensize-1;
- real_mousecol = line_maxcol(termw, mouselin);
- }
-
- /*
- * If we are above the anchor, then the "interesting" side of the
- * click extent is mousecol_l, else it is mousecol_h.
- *
- * Again, we are not taking into account any intermediate double-width
- * lines, but hopefully that's OK.
- */
- if ((MAXCOL * termw->from_lin + termw->from_col) >
- (MAXCOL * mouselin + real_mousecol))
- {
- i = mousecol_l; /* "above" the anchor point */
-
- /* but if we were below the anchor, restore and swap */
- if ((MAXCOL * termw->from_lin + termw->from_col) <
- (MAXCOL * termw->to_lin + termw->to_col))
- {
- /* Unselect current text. */
- invert_text(termw, termw->from_lin, termw->from_col,
- termw->to_lin, termw->to_col);
-
- termw->from_lin = old_to_lin;
- termw->from_col = old_to_col;
- termw->to_lin = old_from_lin;
- termw->to_col = old_from_col;
-
- /* Reselect new (old) text. */
- invert_text(termw, termw->from_lin, termw->from_col,
- termw->to_lin, termw->to_col);
- }
- } else {
- i = mousecol_h; /* "below" the anchor point */
-
- /* but if we were above the anchor, restore and swap */
- if ((MAXCOL * termw->from_lin + termw->from_col) >
- (MAXCOL * termw->to_lin + termw->to_col))
- {
- /* Unselect current text. */
- invert_text(termw, termw->from_lin, termw->from_col,
- termw->to_lin, termw->to_col);
-
- termw->from_lin = old_from_lin;
- termw->from_col = old_from_col;
- termw->to_lin = old_to_lin;
- termw->to_col = old_to_col;
-
- /* Reselect new (old) text. */
- invert_text(termw, termw->from_lin, termw->from_col,
- termw->to_lin, termw->to_col);
- }
- }
-
-
- /*
- * If any new text was selected, invert it.
- */
- if ((i != termw->to_col) || (mouselin != termw->to_lin)) {
- invert_text(termw, termw->to_lin, termw->to_col, mouselin, i);
- termw->to_lin = mouselin;
- termw->to_col = i;
- }
- }
-
- /* make from < to */
- if ((MAXCOL * termw->from_lin + termw->from_col) >
- (MAXCOL * termw->to_lin + termw->to_col)) {
- i = termw->to_lin;
- termw->to_lin = termw->from_lin;
- termw->from_lin = i;
- i = termw->to_col;
- termw->to_col = termw->from_col;
- termw->from_col = i;
- }
-
- if ((termw->from_lin != termw->to_lin) ||
- (termw->from_col != termw->to_col))
- termw->have_selection = TRUE;
- else
- termw->have_selection = FALSE;
-
- /*
- * If the mouse wasn't down long enough to be a drag, time double click
- * from the mouse UP.
- */
- if (((TickCount () - prev_mouse_up) <= GetDblTime())
- && (ABS(MousePt.v - prev_mouse_point.v) < termw->lineheight)
- && (ABS(MousePt.h - prev_mouse_point.h) < termw->charwidth)) {
- prev_mouse_up = TickCount (); /* save when the mouse went up */
- }
- }
-
- /* (PWP) if the selection is within [tlin,blin], then remove it */
-
- void maybe_nuke_selection (struct termw *termw, int tlin, int blin)
- {
- int my_to_lin;
-
- if (!termw->have_selection)
- return;
-
- my_to_lin = termw->to_lin;
- if ((termw->to_col == 0) && (termw->from_lin != termw->to_lin))
- my_to_lin--;
-
- if (!(((tlin < termw->from_lin) && (blin < termw->from_lin))
- || ((tlin > my_to_lin) && (blin > my_to_lin))) ) {
- termw->have_selection = FALSE;
- invert_text(termw,
- termw->from_lin,
- termw->from_col,
- termw->to_lin,
- termw->to_col);
- }
- }
-
- /*
- * Copy the current selction to the (internal) clipboard.
- *
- * This is an external, but we don't have to save the GrafPort
- * because we don't do anything to the screen.
- */
- scr_copy (struct termw *termw)
- {
- int lin, i, rcol;
- long sz;
- char *dp;
- ScrapStuff *pss;
-
- if (myclip_h == NIL) {
- printerr("scr_copy: clip handle not allocated", 0);
- return;
- }
-
- if (termw->have_selection) {
- /****** find out how big the text to copy is ******/
- if (termw->from_lin == termw->to_lin) {
- /*
- * If we are copying to the end of line, we should really only copy
- * a CR instead of all those trailing blanks. So we must find out
- * where the last real character is.
- */
- if (termw->to_col >= line_maxcol(termw, termw->to_lin)) {
- for (rcol = line_maxcol(termw, termw->to_lin); rcol>0; rcol--)
- /* last */
- if ((termw->scr[termw->to_lin][rcol-1] != ' ')
- || (termw->scr_attrs[termw->to_lin][rcol-1] != 0))
- break;
- } else {
- rcol = termw->to_col;
- }
- sz = rcol - termw->from_col + 1;
- } else {
- for (rcol = line_maxcol(termw, termw->from_lin);
- rcol > termw->from_col; rcol--) /* first */
- if ((termw->scr[termw->from_lin][rcol-1] != ' ')
- || (termw->scr_attrs[termw->from_lin][rcol-1] != 0))
- break;
- /* chars plus one for the termw->newline */
- sz = rcol - termw->from_col + 1;
-
- /* in between */
- for (lin = termw->from_lin+1; lin < termw->to_lin; lin++) {
- for (rcol = line_maxcol(termw, lin); rcol > 0; rcol--)
- if ((termw->scr[lin][rcol-1] != ' ')
- || (termw->scr_attrs[lin][rcol-1] != 0))
- break;
- sz += rcol + 1; /* chars plus one for the termw->newline */
- }
-
- if (termw->to_col >= line_maxcol(termw, termw->to_lin)) {
- /***** find the last real character *****/
- for (rcol = line_maxcol(termw, termw->to_lin); rcol>0; rcol--)
- /* last */
- if ((termw->scr[termw->to_lin][rcol-1] != ' ')
- || (termw->scr_attrs[termw->to_lin][rcol-1] != 0))
- break;
- } else {
- rcol = termw->to_col;
- }
- sz += rcol; /* chars */
- if (termw->to_col >= line_maxcol(termw, termw->to_lin))
- sz++;
- }
-
- /***** Reality Check *****/
- if (sz > 8192) {
- printerr("Too big to copy: ", sz);
- return;
- }
-
- /****** allocate and lock a buffer for the text ******/
- if (sz > GetHandleSize ((Handle) myclip_h)) {
- HUnlock((Handle) myclip_h);
- /* $$$ this may fail, but we have no way of knowing. */
- /* (in assembler, this will return a result, but the pascal */
- /* version is a PROCEDURE, so we get zilch. If this fails */
- /* we will probably crash the Mac...) */
- SetHandleSize((Handle) myclip_h, sz);
- }
- HLock((Handle) myclip_h);
- dp = *myclip_h;
-
- /****** copy the characters over to the clip ******/
- if (termw->from_lin == termw->to_lin) {
- if (termw->to_col >= line_maxcol(termw, termw->to_lin)) {
- for (rcol = line_maxcol(termw, termw->to_lin); rcol>0; rcol--)
- /* last */
- if ((termw->scr[termw->to_lin][rcol-1] != ' ')
- || (termw->scr_attrs[termw->to_lin][rcol-1] != 0))
- break;
- } else {
- rcol = termw->to_col;
- }
- for (i = termw->from_col; i < rcol; i++)
- *dp++ = termw->scr[termw->from_lin][i];
- if (termw->to_col >= line_maxcol(termw, termw->to_lin))
- *dp++ = CR; /* add the return */
- } else {
- /* trim off spaces */
- for (rcol = line_maxcol(termw, termw->from_lin);
- rcol > termw->from_col; rcol--) /* first */
- if ((termw->scr[termw->from_lin][rcol-1] != ' ')
- || (termw->scr_attrs[termw->from_lin][rcol-1] != 0))
- break;
- for (i = termw->from_col; i < rcol; i++)
- *dp++ = termw->scr[termw->from_lin][i];
- *dp++ = CR;
-
- /* in between */
- for (lin = termw->from_lin+1; lin < termw->to_lin; lin++) {
- for (rcol = line_maxcol(termw, lin); rcol > 0; rcol--)
- if ((termw->scr[lin][rcol-1] != ' ')
- || (termw->scr_attrs[lin][rcol-1] != 0))
- break;
- for (i = 0; i < rcol; i++)
- *dp++ = termw->scr[lin][i];
- *dp++ = CR;
- }
-
- if (termw->to_col == line_maxcol(termw, termw->to_lin)) {
- for (rcol = line_maxcol(termw, termw->to_lin); rcol>0; rcol--)
- /* last */
- if ((termw->scr[termw->to_lin][rcol-1] != ' ')
- || (termw->scr_attrs[termw->to_lin][rcol-1] != 0))
- break;
- } else {
- rcol = termw->to_col;
- }
- for (i = 0; i < rcol; i++)
- *dp++ = termw->scr[termw->to_lin][i];
- if (termw->to_col >= line_maxcol(termw, termw->to_lin))
- *dp++ = CR;
- }
- myclip_size = (dp - *myclip_h);
-
- /****** check to make sure we didn't overflow the clipboard ******/
- if (myclip_size > sz)
- macfatal ("Overflow! myclip_size - sz ==",
- myclip_size - sz);
-
-
- /****** Now copy our internal clipboard to the Macintosh one *****/
- /*
- * $$$ at this point we really should allocate a second buffer,
- * and copy the characters of our buffer into it, converting them
- * from whatever ISO set we are displaying with to the Mac char set.
- */
- ZeroScrap();
- if (PutScrap(myclip_size, 'TEXT', *myclip_h) != noErr)
- printerr("Couldn't PutScrap", 0);
-
- pss = InfoScrap();
- my_scrapcount = pss->scrapCount; /* save this to see if the user */
- /* cuts/copies outside of us */
-
- /****** We are done. Unlock the handle ******/
- HUnlock((Handle) myclip_h);
- } else {
- SysBeep(3);
- }
- }
-
- /*
- * Paste the clipboard into the terminal, by "typing" it in.
- *
- * This also is an external, but we don't have to save the GrafPort
- * because the only time we do anything to the screen, it's through
- * inpchars(), which saves the GrafPort itself.
- */
- scr_paste (struct termw *termw)
- {
- char *cp, *endp;
- char **h;
- long l, o;
- ScrapStuff *pss;
-
- pss = InfoScrap();
- if (my_scrapcount == pss->scrapCount) {
- /* if this is still the same scrap that we made */
- if (myclip_size > 0) {
- HLock((Handle) myclip_h);
- cp = *myclip_h;
- endp = cp + myclip_size;
- for (; cp < endp; cp++) {
- OutputChar(termw, *cp);
- if (*cp == CR)
- waitasec (termw);
- }
- HUnlock((Handle) myclip_h);
- } else {
- SysBeep(3);
- }
- } else { /* we have to get the TEXT scrap from the clipboard */
- h = NewHandle(0);
- l = GetScrap(h, 'TEXT', &o);
- if (l <= 0) {
- SysBeep(3);
- } else {
- HLock((Handle) h);
- cp = *h;
- endp = cp + l;
- for (; cp < endp; cp++) {
- /* $$$ Should convert *cp to whatever ISO font we are typing */
- OutputChar(termw, *cp);
- if (*cp == CR)
- waitasec (termw);
- }
- HUnlock((Handle) h);
- } /* end if (l > 0) */
- DisposHandle(h);
- }
- }
-
- /*
- * Paste into the command window.
- */
- cmd_paste (struct termw *termw)
- {
- char *cp, *endp;
- char **h;
- long l, o;
- ScrapStuff *pss;
-
- pss = InfoScrap();
- if (my_scrapcount == pss->scrapCount) {
- /* if this is still the same scrap that we made */
- if (myclip_size > 0) {
- HLock((Handle) myclip_h);
- cp = *myclip_h;
- endp = cp + myclip_size;
- for (; cp < endp; cp++) {
- writecbc(*cp);
- if (*cp == CR)
- waitasec (termw);
- }
- HUnlock((Handle) myclip_h);
- } else {
- SysBeep(3);
- }
- } else { /* we have to get the TEXT scrap from the clipboard */
- h = NewHandle(0);
- l = GetScrap(h, 'TEXT', &o);
- if (l <= 0) {
- SysBeep(3);
- } else {
- HLock((Handle) h);
- cp = *h;
- endp = cp + l;
- for (; cp < endp; cp++) {
- /* $$$ Should convert *cp to whatever ISO font we are typing */
- writecbc(*cp);
- if (*cp == CR)
- waitasec (termw);
- }
- HUnlock((Handle) h);
- } /* end if (l > 0) */
- DisposHandle(h);
- }
- }
-
-
- /****************************************************************************/
- /****************************************************************************/
-
- #ifdef COMMENT
- show_inval_rgn(w)
- WindowPeek w;
- {
- RgnHandle r = NewRgn();
-
- CopyRgn (w->updateRgn, r);
- OffsetRgn(r, /* convert to local grafport coords */
- (((w->port).portBits).bounds).left,
- (((w->port).portBits).bounds).top);
- FillRgn(r, qd.gray);
- DisposeRgn(r);
- waitnoinput ();
- waitnoinput ();
- waitnoinput ();
- waitnoinput ();
- }
- #endif /* COMMENT */
-
- /****************************************************************************/
- /*
- * PWP: actually do all the scrolling and refreshing we have promised to
- * do.
- *
- * Method (and many var and fcn names) stolen from X11 xterm.
- */
- /****************************************************************************/
- void flushscroll (struct termw *termw)
- {
- register int i, now;
- Rect r; /* , opened_r cannot be register */
- GrafPtr currWindow; /* cannot be register */
- RgnHandle newupdateRgn;
- Rect *rp;
- int lin;
- int vtoplin, vbotlin, vleftcol, vrightcol;
-
- if (termw->scroll_amount == 0) {
- printerr ("flushscroll() called with no scroll to flush", 0);
- return;
- }
-
- /* should hide the cursor here if not already hidden */
-
- /* (PWP) if our selected region overlaps, but is not enclosed by the region
- we want to scroll, then remove it, because the region no longer contains
- what the user thought it did. */
- if (termw->have_selection && (termw->saved_tlin != toplin) &&
- (termw->saved_blin != botlin) &&
- ((termw->from_lin < termw->saved_tlin) ||
- (termw->to_lin > termw->saved_blin)) &&
- ((termw->to_lin > termw->saved_tlin) ||
- (termw->from_lin < termw->saved_blin))) {
- termw->have_selection = FALSE;
- invert_text(termw, termw->from_lin, termw->from_col, termw->to_lin,
- termw->to_col);
- }
-
- if (!termw->in_front) {
- /* if not in front, compensate update region for scrolling */
- GetPort (&currWindow);
- /* scroll the old updateRgn */
- OffsetRgn (((WindowPeek) currWindow)->updateRgn, 0,
- -termw->lineheight);
- }
-
-
- /*
- * Do the scrolling
- */
- makerect(termw,&r, termw->saved_tlin, 0,
- termw->saved_blin - termw->saved_tlin + 1, MAXCOL);
- newupdateRgn = NewRgn();
-
- if (termw->smoothscroll && termw->in_front) {
- int dir = 1; /* direction */
- if (termw->scroll_amount < 0)
- dir = -1;
- for (i = 1; i <= termw->scroll_amount*termw->lineheight*dir; i += 1) {
- /* PWP: wait for a vertical reblank (in a sneaky way) */
- now = TickCount ();
- while (TickCount () == now)
- /* wait... */ ;
- ScrollRect (&r, 0, dir, newupdateRgn);
- }
- } else {
- ScrollRect (&r, 0, termw->scroll_amount * termw->lineheight,
- newupdateRgn);
- }
-
- /*
- * NOTE: We don't add the newupdateRgn to the actual window update region,
- * but instead we just update all the lines that are in the region now.
- * This is faster, gives a smoother appearance to background windows, and
- * avoids an apparent bug in the Mac that causes multiplely scrolled
- * update regions to be incorrect.
- */
-
-
- termw->scroll_amount = 0; /* we've done it now */
-
- /*
- * Find the intersection of what we just opened up and the visible portion
- * of the screen, and update all the lines in that rectangle.
- */
- rp = &(**(newupdateRgn)).rgnBBox;
-
- /* show the region to be updated -- only for debugging */
- /* FillRgn(newupdateRgn, qd.gray); */
- /* FillRect (rp, qd.gray); */
-
- /* Find the characters that bound this rectangle */
- recttocharpos (termw, rp, &vtoplin, &vleftcol, &vbotlin, &vrightcol);
-
- /* Make sure we pick up any extra refresh region */
- if (termw->refresh_amount < 0) { /* scrolling forward (UP) */
- if (vtoplin > termw->saved_blin + termw->refresh_amount)
- vtoplin = termw->saved_blin + termw->refresh_amount;
- } else if (termw->refresh_amount > 0) { /* scrolling backward (DOWN) */
- if (vbotlin < termw->saved_tlin + termw->refresh_amount - 1)
- vbotlin = termw->saved_tlin + termw->refresh_amount - 1;
- }
-
- /* bounds limit it to the actual screen area (again) */
- if (vtoplin < 0) vtoplin = 0;
- if (vbotlin > termw->screensize) vbotlin = termw->screensize;
-
- lin = termw->display_topline + vtoplin;
- for (i = vtoplin; i < vbotlin; i++) {
- makerect(termw, &r, i, vleftcol, 1, (vrightcol - vleftcol));
-
- /*
- * According to IM 1 pp 185, RectInRgn isn't always exact, so we might
- * try the more exact way if this isn't good enough.
- */
- if (RectInRgn(&r, newupdateRgn)) {
- draw_line_w_attrs(termw, lin, i, vleftcol, vrightcol, 0);
-
- /*
- * If we just drew the line that flushbuf thinks is pending,
- * say we have done so in order to avoid drawing that line twice.
- */
- if (i == termw->curlin)
- termw->out_maxcol = 0;
- }
- lin++;
- }
-
- DisposeRgn(newupdateRgn);
-
- termw->refresh_amount = 0;
- }
-
-
- /****************************************************************************/
- /*
- * (UoR)
- *
- * Scroll lines within the scroll region upwards from line tlin
- * to line blin (lines are assumed to be in the region)
- *
- * (PWP) scroll_screen is the combination of scroll_up and scroll_down.
- * dir is the number of lines to scroll, <0 if up, >0 if down.
- * (actually, right now only -1 and 1 are handled.)
- */
- /****************************************************************************/
- void scroll_screen (termw, tlin, blin, delta)
- /* these are in scr[][] cordinates */
- struct termw *termw;
- register int tlin;
- register int blin;
- register int delta;
- {
- register int i, now;
- char *savedline, *savedattr; /* temporary to hold screen line pointer */
- unsigned char savedlattr;
-
- /*
- * flush out any pending characters.
- *
- * $$$ I bet this is the piece of bogus code that was causing me all the
- * trouble. We NEED to do this, or else keep track of where out_mincol and
- * out_maxcol were when we set up the scroll for the first time, so that
- * we don't mistakenly miss drawing the pending stuff.
- */
- if (!termw->scroll_amount && termw->out_maxcol)
- flushbuf(termw);
-
- /*
- * See if we are scrolling something different and have to flush
- * our pending scroll.
- * We do if asked to scroll something different than the current
- * scrolling rgn, or if we are changing direction, or if we have
- * already collected an entire scrolling region worth of scroll to do.
- */
- if (termw->scroll_amount) {
- i = termw->scroll_amount + delta;
- if (i < 0) i = -i; /* set i to ABS( old scroll plus new scroll ) */
- if (termw->smoothscroll ||
- (tlin != termw->saved_tlin) ||
- (blin != termw->saved_blin) ||
- ((termw->scroll_amount > 0) && (delta < 0)) ||
- ((termw->scroll_amount < 0) && (delta > 0)) ||
- (i >= (termw->saved_blin - termw->saved_tlin)))
- {
- flushscroll(termw);
- }
- }
-
- /*
- * Save up how much to scroll and where for later...
- */
- termw->saved_tlin = tlin;
- termw->saved_blin = blin;
- termw->scroll_amount += delta;
- /*
- * Should really set termw->refresh_amount to 0, then add to it
- * when we "draw" characters onto lines, but this is safe.
- */
- termw->refresh_amount += delta;
-
- /* printerr("termw->scroll_amount now ", scroll_amount); */
-
- if (delta < 0) /* if scrolling UP (forwards) */
- {
- /* adjust the internal character buffers */
- if ((tlin == toplin) && (blin == botlin)) { /* if whole screen */
- termw->display_totlines -= delta; /* remember delta is negitive */
- if (termw->display_totlines > MAX_SCREENSIZE)
- termw->display_totlines = MAX_SCREENSIZE; /* bounds */
- /*top of saved buffer*/
- tlin = termw->screensize - termw->display_totlines;
- }
- for (now = 0; now < -delta; now++) {
- savedline = termw->scr[tlin];
- savedattr = termw->scr_attrs[tlin];
- savedlattr = termw->line_attrs[tlin];
- for (i = tlin+1; i <= blin; i++) {
- termw->scr[i-1] = termw->scr[i];
- termw->scr_attrs[i-1] = termw->scr_attrs[i];
- termw->line_attrs[i-1] = termw->line_attrs[i];
- }
- termw->scr[blin] = savedline;
- termw->scr_attrs[blin] = savedattr;
- termw->line_attrs[blin] = savedlattr;
-
- zeroline(termw, blin, 1); /* clear the line */
- }
-
- /* adjust selection */
- if (termw->have_selection && (termw->from_lin >= tlin) &&
- (termw->to_lin <= blin))
- {
- termw->from_lin += delta;
- if (termw->from_lin < termw->screensize - MAX_SCREENSIZE)
- termw->from_lin = termw->screensize - MAX_SCREENSIZE;
- termw->to_lin += delta;
- if (termw->to_lin < termw->screensize - MAX_SCREENSIZE)
- termw->to_lin = termw->screensize - MAX_SCREENSIZE;
- }
- }
- else /* else scrolling DOWN (reverse scroll) */
- {
- /* adjust the internal buffers */
- for (now = 0; now < delta; now++) {
- savedline = termw->scr[blin];
- savedattr = termw->scr_attrs[blin];
- savedlattr = termw->line_attrs[blin];
- for (i = blin-1; i >= tlin; i--) {
- termw->scr[i+1] = termw->scr[i];
- termw->scr_attrs[i+1] = termw->scr_attrs[i];
- termw->line_attrs[i+1] = termw->line_attrs[i];
- }
- termw->scr[tlin] = savedline;
- termw->scr_attrs[tlin] = savedattr;
- termw->line_attrs[tlin] = savedlattr;
-
- zeroline(termw, tlin, 1);
- }
-
- /* adjust selection */
- if (termw->have_selection && (termw->from_lin >= tlin) &&
- (termw->to_lin <= blin))
- {
- termw->from_lin += delta;
- if (termw->from_lin > botlin) termw->from_lin = botlin;
- termw->to_lin += delta;
- if (termw->to_lin > botlin) termw->to_lin = botlin;
- }
- }
-
- /*
- * but if we are smooth (slow) scrolling and in front, do the scroll now.
- * must do this after adjusting internal buffers, so that the refresh
- * lines don't get confused.
- */
- if (termw->smoothscroll && termw->in_front)
- flushscroll(termw);
- } /* scroll_up */
-
- /****************************************************************************/
- /* redraw the terminal screen (we got a redraw event) */
- /****************************************************************************/
- term_redraw (struct termw *termw)
- {
- int i, lin;
- int vtoplin, vbotlin, vleftcol, vrightcol;
- Rect r, *rp;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- if (termw->screeninvert) {
- BackPat(qd.black);
- PenPat(qd.white);
- } else {
- BackPat(qd.white);
- PenPat(qd.black);
- }
-
- if (termw->scroll_amount)
- flushscroll(termw);
-
- #ifdef COMMENT
- r = terminalWindow->portRect; /* copy the window size */
- /* r.right -= 15; */ /* subtract control */
- /* PWP: clear the screen first */
- /* makerect(termw,&r, 0, 0, termw->screensize, MAXCOL); */
- /* EraseRect (&r); */
- #endif /* COMMENT */
-
- /* See if the scroll bar and grow box need to be updated */
- r = termw->window->portRect; /* copy of the window size */
- /* r.left = r.right - 16; */
- r.left = rightMARGIN;
- if (RectInRgn (&r, termw->window->visRgn))
- {
- termw->scroll_drawn = -1; /* mark scroll bar invalid */
- EraseRect (&r);
- /* don't add to invalid while redrawing invalid */
- draw_grow_and_erase_line(termw, 0);
- DrawControls (termw->window);
- }
-
- /* Update area above first line */
- r = termw->window->portRect; /* copy of the window size */
- r.bottom = r.top + TOPMARGIN;
- r.right -= 16;
- if (RectInRgn (&r, termw->window->visRgn))
- EraseRect (&r);
-
- /* Update area below last line */
- r = termw->window->portRect; /* copy of the window size */
- r.top = termw->bottommargin - 1;
- r.right -= 16;
- if (RectInRgn (&r, termw->window->visRgn))
- EraseRect (&r);
-
- /* Update area to the left of first column */
- r = termw->window->portRect; /* copy of the window size */
- r.top = r.top + TOPMARGIN;
- r.bottom = termw->bottommargin;
- r.right = LEFTMARGIN;
- if (RectInRgn (&r, termw->window->visRgn))
- EraseRect (&r);
-
-
- /* update_vscroll(termw); */
- /* SetCtlValue (termw->t_vscroll, GetCtlValue (t_vscroll)); */
-
- #ifdef COMMENT
- lin = termw->display_topline;
- for (i = 0; i < termw->screensize; i++) {
- makerect(termw,&r, i, 0, 1, MAXCOL);
- if (RectInRgn (&r, termw->window->visRgn))
- draw_line_w_attrs(termw, lin, i, 0, MAXCOL, 1);
- lin++;
- }
- #endif
-
- rp = &(**(termw->window->visRgn)).rgnBBox;
-
- /* Find the characters that bound this rectangle */
- recttocharpos(termw, rp, &vtoplin, &vleftcol, &vbotlin, &vrightcol);
-
- #ifdef COMMENT
- debug(F101,"term_redraw bounds vtoplin","",vtoplin);
- debug(F101,"term_redraw bounds vbotlin","",vbotlin);
- debug(F101,"term_redraw bounds vleftcol","",vleftcol);
- debug(F101,"term_redraw bounds vrightcol","",vrightcol);
- #endif
-
- lin = termw->display_topline + vtoplin;
- for (i = vtoplin; i < vbotlin; i++) {
- makerect(termw, &r, i, 0, 1, MAXCOL);
- if (RectInRgn (&r, termw->window->visRgn))
- draw_line_w_attrs(termw, lin, i, vleftcol, vrightcol, 1);
- lin++;
- }
-
-
- if (termw->have_selection)
- invert_text(termw,
- termw->from_lin,
- termw->from_col,
- termw->to_lin,
- termw->to_col);
-
- /* (UoR) only if cursor is showing */
- if (termw->cur_drawn && termw->cursor_invert) {
- termw->cursor_invert = FALSE; /* (UoR) make sure we draw it */
- cursor_draw(termw); /* redraw cursor */
- termw->last_flash = TickCount (); /* (UoR) reset timer */
- }
-
- SetPort (savePort); /* there just has to be a better way */
- } /* term_redraw */
-
- draw_grow_and_erase_line (struct termw *termw, int invalidate_it)
- {
- Rect r;
-
- DrawGrowIcon (termw->window);
- /* erase the bottom scroll line (but only if inverted screen) */
- if (!termw->screeninvert) {
- PenMode(patBic);
- MoveTo(0, (termw->window->portRect).bottom - 15);
- LineTo((termw->window->portRect).right - 15,
- (termw->window->portRect).bottom - 15);
- PenMode(patCopy);
- }
-
- if (invalidate_it) {
- r.top = (termw->window->portRect).bottom - 16;
- r.bottom = (termw->window->portRect).bottom - 14;
- r.left = 0;
- r.right = (termw->window->portRect).right - 16;
- InvalRect(&r);
- }
- }
-
- term_activate (struct termw *termw, int mod)
- {
- GrafPtr savePort;
-
- GetPort (&savePort);
- SetPort (termw->window);
-
- cursor_erase (termw); /* remove cursor from screen */
- termw->in_front = mod & activeFlag;
- if (termw->in_front) {
- UpdateOptKey(1);
- DisableItem(menus[EDIT_MENU], UNDO_EDIT);
- DisableItem(menus[EDIT_MENU], CLEAR_EDIT);
- } else {
- UpdateOptKey(0);
- EnableItem(menus[EDIT_MENU], UNDO_EDIT);
- EnableItem(menus[EDIT_MENU], CLEAR_EDIT);
- }
- /* these do the right thing for background too */
- update_vscroll (termw);
- draw_grow_and_erase_line(termw, 1);
- cursor_draw(termw);
-
- SetPort (savePort);
- }
-
- /*
- * This CAN be called external to inpchars(), so save and restore the
- * GrafPort just in case.
- */
- set_term_invert (struct termw *termw, int new_inv)
- {
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- if (new_inv == termw->screeninvert)
- return;
-
- if (new_inv) {
- BackPat (qd.black); /* (UoR) use black background */
- PenPat(qd.white);
- termw->screeninvert = TRUE;
- } else {
- BackPat (qd.white);
- PenPat(qd.black);
- termw->screeninvert = FALSE;
- }
- InvalRect(&termw->window->portRect);/* invalidate whole window rectangle */
- SetPort (savePort); /* there just has to be a better way */
- }
-
- /****************************************************************************/
- /* sizevscroll - called when window is created and after a window grow */
- /* sequence to resize the scroll window's bars. */
- /****************************************************************************/
- void sizevscroll (struct termw *termw)
- {
- register Rect *r;
-
- if (!termw)
- DebugStr("\psizevscroll called with termw == NULL");
-
- r = &termw->window->portRect;/* window size */
- HideControl (termw->t_vscroll);
-
- MoveControl (termw->t_vscroll, r->right - 15, r->top - 1);
- SizeControl (termw->t_vscroll, 16, r->bottom - r->top - 13);
-
- SetCtlMin (termw->t_vscroll, 0);
- termw->scroll_drawn = -1; /* mark scroll bar invalid */
- update_vscroll(termw);
- ShowControl (termw->t_vscroll);
- }
-
- /****************************************************************************/
- /* initalize the terminal emulator. */
- /****************************************************************************/
- init_term (struct termw *termw)
- {
- register int i, j;
- register char *scp, *acp;
- char *scr_cp, *attr_cp;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- termw->topmargin = TOPMARGIN; /* Edges of adjustable window */
- termw->bottommargin = bottomMARGIN;
-
- if ((scr_cp = (char *)NewPtr(((long)(MAXCOL+1) * (long) MAX_SCREENSIZE)))
- == NIL)
- macfatal("Could not allocate screen buffer", 0);
-
- if ((attr_cp = (char *)NewPtr(((long)(MAXCOL+1) * (long) MAX_SCREENSIZE)))
- == NIL)
- macfatal("Could not allocate screen attribute buffer", 0);
-
- if ((termw->real_scr = (ucharptr *) NewPtr ((long)(MAX_SCREENSIZE)
- * (long) sizeof(ucharptr))) == NIL)
- macfatal("Could not allocate screen buffer", 0);
-
- if ((termw->real_attrs = (ucharptr *) NewPtr ((long)(MAX_SCREENSIZE)
- * (long) sizeof(ucharptr))) == NIL)
- macfatal("Could not allocate screen buffer", 0);
-
- if ((termw->real_ln_attrs
- = (unsigned char *) NewPtr ((long)(MAX_SCREENSIZE)
- * (long) sizeof(unsigned char))) == NIL)
- macfatal("Could not allocate screen buffer", 0);
-
- for (i = 0; i < MAX_SCREENSIZE; i++) {
- /* divvy up screen buffer */
- termw->real_scr[i] = scr_cp + (i * (MAXCOL+1));
- /* divvy up screen attribute buf */
- termw->real_attrs[i] = attr_cp + (i * (MAXCOL+1));
-
- scp = termw->real_scr[i];
- acp = termw->real_attrs[i];
- j = MAXCOL;
- do { /* put normal spaces in all columns */
- *scp++ = ' ';
- *acp++ = 0;
- } while (--j > 0);
- *scp = ' '; /* Terminate the lines as strings */
- *acp = 0; /* Terminate the attrs as strings */
- termw->real_ln_attrs[i] = VT_SNGL; /* reset line attributes */
- }
-
- termw->scr = &termw->real_scr[MAX_SCREENSIZE - termw->screensize];
- if (termw->scr[0] == NIL)
- macfatal("init_term: scr assignment botched for [0]", 0);
- if (termw->scr[termw->screensize-1] == NIL)
- macfatal("\
- init_term: scr assignment botched for [termw->screensize-1]", 0);
-
- termw->scr_attrs = &termw->real_attrs[MAX_SCREENSIZE - termw->screensize];
- if (termw->scr_attrs[0] == NIL)
- macfatal("init_term: scr assignment botched for [0]", 0);
- if (termw->scr_attrs[termw->screensize-1] == NIL)
- macfatal("\
- init_term: scr assignment botched for [termw->screensize-1]", 0);
-
- termw->line_attrs = &termw->real_ln_attrs[MAX_SCREENSIZE
- - termw->screensize];
-
- termw->scrtop = toplin; /* Scrolling region equals all */
- termw->scrbot = botlin;
-
- termw->scroll_amount = 0; /* no pending scroll */
- termw->refresh_amount = 0; /* no pending refresh */
- termw->saved_tlin = 0;
- termw->saved_blin = 0;
-
- termw->display_topline = toplin; /* init display w/elevator at bottom */
- termw->display_totlines = termw->screensize;
- makerect(termw,&termw->ScreenRect, 0, 0, termw->screensize, MAXCOL);
- /* (UoR) full screen rectangle */
-
- SizeWindow(termw->window,
- rightMARGIN + 1 + 16, /* add extra to side for asthetics */
- bottomMARGIN + TOPMARGIN, /* add extra to bottom for asthetics */
- FALSE);
- /* PWP: make the window match it's real size */
-
- termw->t_vscroll = GetNewControl (RCMDVSCROLL, termw->window);
- termw->scroll_drawn = -1; /* mark scroll bar invalid */
- sizevscroll(termw);
-
- InitKeyStuff(); /* find the original KCHR keymaps */
-
- #ifdef COMMENT
- draw_grow_and_erase_line(0); /* it's new so don't invalidate it */
- #endif
-
- /* ClipRect(&termw->ScreenRect); */
-
- SetPort (savePort); /* there just has to be a better way */
- } /* init_term */
-
- /****************************************************************************/
- /* grow_term_to(termw, size) -- change the size of the terminal window to size.
- this is called by growterm() (see below) and the terminal settings dialog
- handler (termsetdialog()).
- /****************************************************************************/
- grow_term_to (struct termw *termw, int size)
- {
- GrafPtr savePort;
-
- GetPort (&savePort);
- SetPort (termw->window);
-
- if ((size < 1) || (size > MAX_SCREENSIZE))
- size = 24; /* the default case */
-
- if (size > termw->display_totlines) {
- /*
- * if getting bigger than we were
- * We would zero out lines from (termw->screensize-size) to
- * (termw->screensize-display_totlines),
- * but these were already zeroed when the original screen was inited.
- */
- termw->display_totlines = size;
- }
-
- /* $$$ Make sure to scroll screen to what will be the new bottom here */
-
- /* adjust cursor row to match stretch */
- termw->curlin += size - termw->screensize;
- if (termw->curlin < 0)
- termw->curlin = 0;
- if (termw->curlin > size-1)
- termw->curlin = size-1;
-
- termw->screensize = size;
- if (termw->screensize > MAX_SCREENSIZE)
- termw->screensize = MAX_SCREENSIZE; /* bounds check */
-
- termw->scr = &termw->real_scr[MAX_SCREENSIZE - termw->screensize];
- termw->scr_attrs = &termw->real_attrs[MAX_SCREENSIZE - termw->screensize];
- termw->line_attrs = &termw->real_ln_attrs[MAX_SCREENSIZE
- - termw->screensize];
-
- termw->bottommargin = bottomMARGIN; /* this changes */
-
- termw->scrtop = toplin; /* Scrolling region equals all */
- termw->scrbot = botlin;
- termw->display_topline = 0; /* re-init display w/elevator at bottom */
- makerect(termw,&termw->ScreenRect, 0, 0, termw->screensize, MAXCOL);
- /* (UoR) full screen rectangle */
-
- SizeWindow(termw->window,
- rightMARGIN + 1 + 16, /* add extra to side for asthetics */
- bottomMARGIN + TOPMARGIN, /* add extra to bottom for asthetics */
- FALSE);
- /* PWP: make the window match it's real size */
- termw->scroll_drawn = -1; /* mark scroll bar invalid */
- sizevscroll(termw); /* size the scroll bars */
-
- /* ClipRect(&termw->ScreenRect); */
-
- /* invalidate whole window rectangle */
- InvalRect (&termw->window->portRect);
-
- SetPort (savePort);
- } /* grow_term_to */
-
- /****************************************************************************/
- /*
- * growterm() -- called when we get a mouse-down in the lower right corner grow
- * box.
- * Probably all right not to save the grafport, but we do anyway just to be
- * double extra safe.
- */
- /****************************************************************************/
- growterm (struct termw *termw, Point *p)
- {
- long gr;
- int height;
- int width;
- int size;
- Rect growRect;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- growRect = qd.screenBits.bounds;
- growRect.top = 50; /* minimal horizontal size */
- growRect.left = rightMARGIN + 18; /* minimal vertical size */
- growRect.right = rightMARGIN + 18; /* minimal vertical size */
-
- gr = GrowWindow (termw->window, *p, &growRect);
-
- if (gr == 0)
- return;
- height = HiWord (gr);
- width = LoWord (gr);
-
- size = (height - (2 * TOPMARGIN)) / termw->lineheight;
- if (size > MAX_SCREENSIZE)
- termw->screensize = MAX_SCREENSIZE; /* bounds check */
- if (size < 1)
- size = 1;
-
- grow_term_to(termw, size);
-
- SetPort (savePort); /* there just has to be a better way */
- } /* growterm */
-
- /****************************************************************************/
- get_term_pos(struct termw *termw, int *top_p, int *left_p)
- {
- Point mypoint;
- GrafPtr savePort;
-
- GetPort (&savePort); /* there just has to be a better way */
- SetPort (termw->window);
-
- mypoint.v = termw->window->portRect.top;
- mypoint.h = termw->window->portRect.left;
- LocalToGlobal(&mypoint);
-
- if (top_p)
- *top_p = mypoint.v;
- if (top_p)
- *left_p = mypoint.h;
-
- SetPort (savePort); /* there just has to be a better way */
- }
-
- set_term_pos(struct termw *termw, int top, int left)
- {
- MoveWindow(termw->window, left, top, TRUE);
- }
-
- /*
- * Junk so Emacs will set local variables to be compatible with Mac/MPW.
- * Should be at end of file.
- * This module was apparently formatted with tabs = 8
- *
- * Local Variables:
- * tab-width: 8
- * End:
- */
-